diff options
Diffstat (limited to 'drivers')
47 files changed, 3725 insertions, 1004 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b89d250f56e7..74e17f19cc33 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -657,6 +657,13 @@ config GPIO_JANZ_TTL | |||
657 | This driver provides support for driving the pins in output | 657 | This driver provides support for driving the pins in output |
658 | mode only. Input mode is not supported. | 658 | mode only. Input mode is not supported. |
659 | 659 | ||
660 | config GPIO_PALMAS | ||
661 | bool "TI PALMAS series PMICs GPIO" | ||
662 | depends on MFD_PALMAS | ||
663 | help | ||
664 | Select this option to enable GPIO driver for the TI PALMAS | ||
665 | series chip family. | ||
666 | |||
660 | config GPIO_TPS6586X | 667 | config GPIO_TPS6586X |
661 | bool "TPS6586X GPIO" | 668 | bool "TPS6586X GPIO" |
662 | depends on MFD_TPS6586X | 669 | depends on MFD_TPS6586X |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 45a388c21d04..6dbcba2e5cac 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o | |||
68 | obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o | 68 | obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o |
69 | obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o | 69 | obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o |
70 | obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o | 70 | obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o |
71 | obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o | ||
71 | obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o | 72 | obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o |
72 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o | 73 | obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o |
73 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o | 74 | obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o |
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c new file mode 100644 index 000000000000..e3a4e56f5a42 --- /dev/null +++ b/drivers/gpio/gpio-palmas.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * TI Palma series PMIC's GPIO driver. | ||
3 | * | ||
4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * Author: Laxman Dewangan <ldewangan@nvidia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms and conditions of the GNU General Public License, | ||
10 | * version 2, as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/mfd/palmas.h> | ||
25 | #include <linux/of.h> | ||
26 | #include <linux/of_device.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | |||
29 | struct palmas_gpio { | ||
30 | struct gpio_chip gpio_chip; | ||
31 | struct palmas *palmas; | ||
32 | }; | ||
33 | |||
34 | static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip) | ||
35 | { | ||
36 | return container_of(chip, struct palmas_gpio, gpio_chip); | ||
37 | } | ||
38 | |||
39 | static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
40 | { | ||
41 | struct palmas_gpio *pg = to_palmas_gpio(gc); | ||
42 | struct palmas *palmas = pg->palmas; | ||
43 | unsigned int val; | ||
44 | int ret; | ||
45 | |||
46 | ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val); | ||
47 | if (ret < 0) { | ||
48 | dev_err(gc->dev, "GPIO_DATA_IN read failed, err = %d\n", ret); | ||
49 | return ret; | ||
50 | } | ||
51 | return !!(val & BIT(offset)); | ||
52 | } | ||
53 | |||
54 | static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset, | ||
55 | int value) | ||
56 | { | ||
57 | struct palmas_gpio *pg = to_palmas_gpio(gc); | ||
58 | struct palmas *palmas = pg->palmas; | ||
59 | int ret; | ||
60 | |||
61 | if (value) | ||
62 | ret = palmas_write(palmas, PALMAS_GPIO_BASE, | ||
63 | PALMAS_GPIO_SET_DATA_OUT, BIT(offset)); | ||
64 | else | ||
65 | ret = palmas_write(palmas, PALMAS_GPIO_BASE, | ||
66 | PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset)); | ||
67 | if (ret < 0) | ||
68 | dev_err(gc->dev, "%s write failed, err = %d\n", | ||
69 | (value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT", | ||
70 | ret); | ||
71 | } | ||
72 | |||
73 | static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, | ||
74 | int value) | ||
75 | { | ||
76 | struct palmas_gpio *pg = to_palmas_gpio(gc); | ||
77 | struct palmas *palmas = pg->palmas; | ||
78 | int ret; | ||
79 | |||
80 | /* Set the initial value */ | ||
81 | palmas_gpio_set(gc, offset, value); | ||
82 | |||
83 | ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, | ||
84 | PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset)); | ||
85 | if (ret < 0) | ||
86 | dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset) | ||
91 | { | ||
92 | struct palmas_gpio *pg = to_palmas_gpio(gc); | ||
93 | struct palmas *palmas = pg->palmas; | ||
94 | int ret; | ||
95 | |||
96 | ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, | ||
97 | PALMAS_GPIO_DATA_DIR, BIT(offset), 0); | ||
98 | if (ret < 0) | ||
99 | dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
104 | { | ||
105 | struct palmas_gpio *pg = to_palmas_gpio(gc); | ||
106 | struct palmas *palmas = pg->palmas; | ||
107 | |||
108 | return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset); | ||
109 | } | ||
110 | |||
111 | static int palmas_gpio_probe(struct platform_device *pdev) | ||
112 | { | ||
113 | struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); | ||
114 | struct palmas_platform_data *palmas_pdata; | ||
115 | struct palmas_gpio *palmas_gpio; | ||
116 | int ret; | ||
117 | |||
118 | palmas_gpio = devm_kzalloc(&pdev->dev, | ||
119 | sizeof(*palmas_gpio), GFP_KERNEL); | ||
120 | if (!palmas_gpio) { | ||
121 | dev_err(&pdev->dev, "Could not allocate palmas_gpio\n"); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | palmas_gpio->palmas = palmas; | ||
126 | palmas_gpio->gpio_chip.owner = THIS_MODULE; | ||
127 | palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); | ||
128 | palmas_gpio->gpio_chip.ngpio = 8; | ||
129 | palmas_gpio->gpio_chip.can_sleep = 1; | ||
130 | palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; | ||
131 | palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; | ||
132 | palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; | ||
133 | palmas_gpio->gpio_chip.set = palmas_gpio_set; | ||
134 | palmas_gpio->gpio_chip.get = palmas_gpio_get; | ||
135 | palmas_gpio->gpio_chip.dev = &pdev->dev; | ||
136 | #ifdef CONFIG_OF_GPIO | ||
137 | palmas_gpio->gpio_chip.of_node = palmas->dev->of_node; | ||
138 | #endif | ||
139 | palmas_pdata = dev_get_platdata(palmas->dev); | ||
140 | if (palmas_pdata && palmas_pdata->gpio_base) | ||
141 | palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base; | ||
142 | else | ||
143 | palmas_gpio->gpio_chip.base = -1; | ||
144 | |||
145 | ret = gpiochip_add(&palmas_gpio->gpio_chip); | ||
146 | if (ret < 0) { | ||
147 | dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | platform_set_drvdata(pdev, palmas_gpio); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static int palmas_gpio_remove(struct platform_device *pdev) | ||
156 | { | ||
157 | struct palmas_gpio *palmas_gpio = platform_get_drvdata(pdev); | ||
158 | |||
159 | return gpiochip_remove(&palmas_gpio->gpio_chip); | ||
160 | } | ||
161 | |||
162 | static struct platform_driver palmas_gpio_driver = { | ||
163 | .driver.name = "palmas-gpio", | ||
164 | .driver.owner = THIS_MODULE, | ||
165 | .probe = palmas_gpio_probe, | ||
166 | .remove = palmas_gpio_remove, | ||
167 | }; | ||
168 | |||
169 | static int __init palmas_gpio_init(void) | ||
170 | { | ||
171 | return platform_driver_register(&palmas_gpio_driver); | ||
172 | } | ||
173 | subsys_initcall(palmas_gpio_init); | ||
174 | |||
175 | static void __exit palmas_gpio_exit(void) | ||
176 | { | ||
177 | platform_driver_unregister(&palmas_gpio_driver); | ||
178 | } | ||
179 | module_exit(palmas_gpio_exit); | ||
180 | |||
181 | MODULE_ALIAS("platform:palmas-gpio"); | ||
182 | MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); | ||
183 | MODULE_DESCRIPTION("GPIO driver for TI Palmas series PMICs"); | ||
184 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index 369a39de4ff3..f9179b2585a9 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c | |||
@@ -100,9 +100,6 @@ static int max8925_onkey_probe(struct platform_device *pdev) | |||
100 | input->dev.parent = &pdev->dev; | 100 | input->dev.parent = &pdev->dev; |
101 | input_set_capability(input, EV_KEY, KEY_POWER); | 101 | input_set_capability(input, EV_KEY, KEY_POWER); |
102 | 102 | ||
103 | irq[0] += chip->irq_base; | ||
104 | irq[1] += chip->irq_base; | ||
105 | |||
106 | error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, | 103 | error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, |
107 | IRQF_ONESHOT, "onkey-down", info); | 104 | IRQF_ONESHOT, "onkey-down", info); |
108 | if (error < 0) { | 105 | if (error < 0) { |
diff --git a/drivers/memstick/host/rtsx_pci_ms.c b/drivers/memstick/host/rtsx_pci_ms.c index f5ddb82dadb7..64a779c58a74 100644 --- a/drivers/memstick/host/rtsx_pci_ms.c +++ b/drivers/memstick/host/rtsx_pci_ms.c | |||
@@ -426,6 +426,9 @@ static void rtsx_pci_ms_request(struct memstick_host *msh) | |||
426 | 426 | ||
427 | dev_dbg(ms_dev(host), "--> %s\n", __func__); | 427 | dev_dbg(ms_dev(host), "--> %s\n", __func__); |
428 | 428 | ||
429 | if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD)) | ||
430 | return; | ||
431 | |||
429 | schedule_work(&host->handle_req); | 432 | schedule_work(&host->handle_req); |
430 | } | 433 | } |
431 | 434 | ||
@@ -441,6 +444,10 @@ static int rtsx_pci_ms_set_param(struct memstick_host *msh, | |||
441 | dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", | 444 | dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", |
442 | __func__, param, value); | 445 | __func__, param, value); |
443 | 446 | ||
447 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD); | ||
448 | if (err) | ||
449 | return err; | ||
450 | |||
444 | switch (param) { | 451 | switch (param) { |
445 | case MEMSTICK_POWER: | 452 | case MEMSTICK_POWER: |
446 | if (value == MEMSTICK_POWER_ON) | 453 | if (value == MEMSTICK_POWER_ON) |
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 391e23e6a647..582bda543520 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c | |||
@@ -531,7 +531,7 @@ static int pm800_probe(struct i2c_client *client, | |||
531 | ret = device_800_init(chip, pdata); | 531 | ret = device_800_init(chip, pdata); |
532 | if (ret) { | 532 | if (ret) { |
533 | dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); | 533 | dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); |
534 | goto err_800_init; | 534 | goto err_subchip_alloc; |
535 | } | 535 | } |
536 | 536 | ||
537 | ret = pm800_pages_init(chip); | 537 | ret = pm800_pages_init(chip); |
@@ -546,10 +546,8 @@ static int pm800_probe(struct i2c_client *client, | |||
546 | err_page_init: | 546 | err_page_init: |
547 | mfd_remove_devices(chip->dev); | 547 | mfd_remove_devices(chip->dev); |
548 | device_irq_exit_800(chip); | 548 | device_irq_exit_800(chip); |
549 | err_800_init: | ||
550 | devm_kfree(&client->dev, subchip); | ||
551 | err_subchip_alloc: | 549 | err_subchip_alloc: |
552 | pm80x_deinit(client); | 550 | pm80x_deinit(); |
553 | out_init: | 551 | out_init: |
554 | return ret; | 552 | return ret; |
555 | } | 553 | } |
@@ -562,9 +560,7 @@ static int pm800_remove(struct i2c_client *client) | |||
562 | device_irq_exit_800(chip); | 560 | device_irq_exit_800(chip); |
563 | 561 | ||
564 | pm800_pages_exit(chip); | 562 | pm800_pages_exit(chip); |
565 | devm_kfree(&client->dev, chip->subchip); | 563 | pm80x_deinit(); |
566 | |||
567 | pm80x_deinit(client); | ||
568 | 564 | ||
569 | return 0; | 565 | return 0; |
570 | } | 566 | } |
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index e671230be2b1..65d7ac099b20 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c | |||
@@ -257,7 +257,7 @@ static int pm805_probe(struct i2c_client *client, | |||
257 | pdata->plat_config(chip, pdata); | 257 | pdata->plat_config(chip, pdata); |
258 | 258 | ||
259 | err_805_init: | 259 | err_805_init: |
260 | pm80x_deinit(client); | 260 | pm80x_deinit(); |
261 | out_init: | 261 | out_init: |
262 | return ret; | 262 | return ret; |
263 | } | 263 | } |
@@ -269,7 +269,7 @@ static int pm805_remove(struct i2c_client *client) | |||
269 | mfd_remove_devices(chip->dev); | 269 | mfd_remove_devices(chip->dev); |
270 | device_irq_exit_805(chip); | 270 | device_irq_exit_805(chip); |
271 | 271 | ||
272 | pm80x_deinit(client); | 272 | pm80x_deinit(); |
273 | 273 | ||
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index 1adb355d86d1..f736a46eb8c0 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c | |||
@@ -48,14 +48,12 @@ int pm80x_init(struct i2c_client *client, | |||
48 | ret = PTR_ERR(map); | 48 | ret = PTR_ERR(map); |
49 | dev_err(&client->dev, "Failed to allocate register map: %d\n", | 49 | dev_err(&client->dev, "Failed to allocate register map: %d\n", |
50 | ret); | 50 | ret); |
51 | goto err_regmap_init; | 51 | return ret; |
52 | } | 52 | } |
53 | 53 | ||
54 | chip->id = id->driver_data; | 54 | chip->id = id->driver_data; |
55 | if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) { | 55 | if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) |
56 | ret = -EINVAL; | 56 | return -EINVAL; |
57 | goto err_chip_id; | ||
58 | } | ||
59 | 57 | ||
60 | chip->client = client; | 58 | chip->client = client; |
61 | chip->regmap = map; | 59 | chip->regmap = map; |
@@ -82,19 +80,11 @@ int pm80x_init(struct i2c_client *client, | |||
82 | } | 80 | } |
83 | 81 | ||
84 | return 0; | 82 | return 0; |
85 | |||
86 | err_chip_id: | ||
87 | regmap_exit(map); | ||
88 | err_regmap_init: | ||
89 | devm_kfree(&client->dev, chip); | ||
90 | return ret; | ||
91 | } | 83 | } |
92 | EXPORT_SYMBOL_GPL(pm80x_init); | 84 | EXPORT_SYMBOL_GPL(pm80x_init); |
93 | 85 | ||
94 | int pm80x_deinit(struct i2c_client *client) | 86 | int pm80x_deinit(void) |
95 | { | 87 | { |
96 | struct pm80x_chip *chip = i2c_get_clientdata(client); | ||
97 | |||
98 | /* | 88 | /* |
99 | * workaround: clear the dependency between pm800 and pm805. | 89 | * workaround: clear the dependency between pm800 and pm805. |
100 | * would remove it after HW chip fixes the issue. | 90 | * would remove it after HW chip fixes the issue. |
@@ -103,10 +93,6 @@ int pm80x_deinit(struct i2c_client *client) | |||
103 | g_pm80x_chip->companion = NULL; | 93 | g_pm80x_chip->companion = NULL; |
104 | else | 94 | else |
105 | g_pm80x_chip = NULL; | 95 | g_pm80x_chip = NULL; |
106 | |||
107 | regmap_exit(chip->regmap); | ||
108 | devm_kfree(&client->dev, chip); | ||
109 | |||
110 | return 0; | 96 | return 0; |
111 | } | 97 | } |
112 | EXPORT_SYMBOL_GPL(pm80x_deinit); | 98 | EXPORT_SYMBOL_GPL(pm80x_deinit); |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ff553babf455..671f5b171c73 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -65,7 +65,7 @@ config MFD_SM501_GPIO | |||
65 | 65 | ||
66 | config MFD_RTSX_PCI | 66 | config MFD_RTSX_PCI |
67 | tristate "Support for Realtek PCI-E card reader" | 67 | tristate "Support for Realtek PCI-E card reader" |
68 | depends on PCI | 68 | depends on PCI && GENERIC_HARDIRQS |
69 | select MFD_CORE | 69 | select MFD_CORE |
70 | help | 70 | help |
71 | This supports for Realtek PCI-Express card reader including rts5209, | 71 | This supports for Realtek PCI-Express card reader including rts5209, |
@@ -95,7 +95,7 @@ config MFD_DM355EVM_MSP | |||
95 | 95 | ||
96 | config MFD_TI_SSP | 96 | config MFD_TI_SSP |
97 | tristate "TI Sequencer Serial Port support" | 97 | tristate "TI Sequencer Serial Port support" |
98 | depends on ARCH_DAVINCI_TNETV107X | 98 | depends on ARCH_DAVINCI_TNETV107X && GENERIC_HARDIRQS |
99 | select MFD_CORE | 99 | select MFD_CORE |
100 | ---help--- | 100 | ---help--- |
101 | Say Y here if you want support for the Sequencer Serial Port | 101 | Say Y here if you want support for the Sequencer Serial Port |
@@ -109,6 +109,7 @@ config MFD_TI_AM335X_TSCADC | |||
109 | select MFD_CORE | 109 | select MFD_CORE |
110 | select REGMAP | 110 | select REGMAP |
111 | select REGMAP_MMIO | 111 | select REGMAP_MMIO |
112 | depends on GENERIC_HARDIRQS | ||
112 | help | 113 | help |
113 | If you say yes here you get support for Texas Instruments series | 114 | If you say yes here you get support for Texas Instruments series |
114 | of Touch Screen /ADC chips. | 115 | of Touch Screen /ADC chips. |
@@ -126,6 +127,7 @@ config HTC_EGPIO | |||
126 | config HTC_PASIC3 | 127 | config HTC_PASIC3 |
127 | tristate "HTC PASIC3 LED/DS1WM chip support" | 128 | tristate "HTC PASIC3 LED/DS1WM chip support" |
128 | select MFD_CORE | 129 | select MFD_CORE |
130 | depends on GENERIC_HARDIRQS | ||
129 | help | 131 | help |
130 | This core driver provides register access for the LED/DS1WM | 132 | This core driver provides register access for the LED/DS1WM |
131 | chips labeled "AIC2" and "AIC3", found on HTC Blueangel and | 133 | chips labeled "AIC2" and "AIC3", found on HTC Blueangel and |
@@ -157,6 +159,7 @@ config MFD_LM3533 | |||
157 | depends on I2C | 159 | depends on I2C |
158 | select MFD_CORE | 160 | select MFD_CORE |
159 | select REGMAP_I2C | 161 | select REGMAP_I2C |
162 | depends on GENERIC_HARDIRQS | ||
160 | help | 163 | help |
161 | Say yes here to enable support for National Semiconductor / TI | 164 | Say yes here to enable support for National Semiconductor / TI |
162 | LM3533 Lighting Power chips. | 165 | LM3533 Lighting Power chips. |
@@ -171,6 +174,7 @@ config TPS6105X | |||
171 | select REGULATOR | 174 | select REGULATOR |
172 | select MFD_CORE | 175 | select MFD_CORE |
173 | select REGULATOR_FIXED_VOLTAGE | 176 | select REGULATOR_FIXED_VOLTAGE |
177 | depends on GENERIC_HARDIRQS | ||
174 | help | 178 | help |
175 | This option enables a driver for the TP61050/TPS61052 | 179 | This option enables a driver for the TP61050/TPS61052 |
176 | high-power "white LED driver". This boost converter is | 180 | high-power "white LED driver". This boost converter is |
@@ -193,7 +197,7 @@ config TPS65010 | |||
193 | config TPS6507X | 197 | config TPS6507X |
194 | tristate "TPS6507x Power Management / Touch Screen chips" | 198 | tristate "TPS6507x Power Management / Touch Screen chips" |
195 | select MFD_CORE | 199 | select MFD_CORE |
196 | depends on I2C | 200 | depends on I2C && GENERIC_HARDIRQS |
197 | help | 201 | help |
198 | If you say yes here you get support for the TPS6507x series of | 202 | If you say yes here you get support for the TPS6507x series of |
199 | Power Management / Touch Screen chips. These include voltage | 203 | Power Management / Touch Screen chips. These include voltage |
@@ -204,7 +208,7 @@ config TPS6507X | |||
204 | 208 | ||
205 | config MFD_TPS65217 | 209 | config MFD_TPS65217 |
206 | tristate "TPS65217 Power Management / White LED chips" | 210 | tristate "TPS65217 Power Management / White LED chips" |
207 | depends on I2C | 211 | depends on I2C && GENERIC_HARDIRQS |
208 | select MFD_CORE | 212 | select MFD_CORE |
209 | select REGMAP_I2C | 213 | select REGMAP_I2C |
210 | help | 214 | help |
@@ -234,7 +238,7 @@ config MFD_TPS6586X | |||
234 | 238 | ||
235 | config MFD_TPS65910 | 239 | config MFD_TPS65910 |
236 | bool "TPS65910 Power Management chip" | 240 | bool "TPS65910 Power Management chip" |
237 | depends on I2C=y && GPIOLIB | 241 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS |
238 | select MFD_CORE | 242 | select MFD_CORE |
239 | select REGMAP_I2C | 243 | select REGMAP_I2C |
240 | select REGMAP_IRQ | 244 | select REGMAP_IRQ |
@@ -251,7 +255,7 @@ config MFD_TPS65912_I2C | |||
251 | bool "TPS65912 Power Management chip with I2C" | 255 | bool "TPS65912 Power Management chip with I2C" |
252 | select MFD_CORE | 256 | select MFD_CORE |
253 | select MFD_TPS65912 | 257 | select MFD_TPS65912 |
254 | depends on I2C=y && GPIOLIB | 258 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS |
255 | help | 259 | help |
256 | If you say yes here you get support for the TPS65912 series of | 260 | If you say yes here you get support for the TPS65912 series of |
257 | PM chips with I2C interface. | 261 | PM chips with I2C interface. |
@@ -260,7 +264,7 @@ config MFD_TPS65912_SPI | |||
260 | bool "TPS65912 Power Management chip with SPI" | 264 | bool "TPS65912 Power Management chip with SPI" |
261 | select MFD_CORE | 265 | select MFD_CORE |
262 | select MFD_TPS65912 | 266 | select MFD_TPS65912 |
263 | depends on SPI_MASTER && GPIOLIB | 267 | depends on SPI_MASTER && GPIOLIB && GENERIC_HARDIRQS |
264 | help | 268 | help |
265 | If you say yes here you get support for the TPS65912 series of | 269 | If you say yes here you get support for the TPS65912 series of |
266 | PM chips with SPI interface. | 270 | PM chips with SPI interface. |
@@ -330,13 +334,13 @@ config TWL4030_POWER | |||
330 | 334 | ||
331 | config MFD_TWL4030_AUDIO | 335 | config MFD_TWL4030_AUDIO |
332 | bool | 336 | bool |
333 | depends on TWL4030_CORE | 337 | depends on TWL4030_CORE && GENERIC_HARDIRQS |
334 | select MFD_CORE | 338 | select MFD_CORE |
335 | default n | 339 | default n |
336 | 340 | ||
337 | config TWL6040_CORE | 341 | config TWL6040_CORE |
338 | bool "Support for TWL6040 audio codec" | 342 | bool "Support for TWL6040 audio codec" |
339 | depends on I2C=y | 343 | depends on I2C=y && GENERIC_HARDIRQS |
340 | select MFD_CORE | 344 | select MFD_CORE |
341 | select REGMAP_I2C | 345 | select REGMAP_I2C |
342 | select REGMAP_IRQ | 346 | select REGMAP_IRQ |
@@ -405,7 +409,7 @@ config MFD_TMIO | |||
405 | 409 | ||
406 | config MFD_T7L66XB | 410 | config MFD_T7L66XB |
407 | bool "Support Toshiba T7L66XB" | 411 | bool "Support Toshiba T7L66XB" |
408 | depends on ARM && HAVE_CLK | 412 | depends on ARM && HAVE_CLK && GENERIC_HARDIRQS |
409 | select MFD_CORE | 413 | select MFD_CORE |
410 | select MFD_TMIO | 414 | select MFD_TMIO |
411 | help | 415 | help |
@@ -413,7 +417,7 @@ config MFD_T7L66XB | |||
413 | 417 | ||
414 | config MFD_SMSC | 418 | config MFD_SMSC |
415 | bool "Support for the SMSC ECE1099 series chips" | 419 | bool "Support for the SMSC ECE1099 series chips" |
416 | depends on I2C=y | 420 | depends on I2C=y && GENERIC_HARDIRQS |
417 | select MFD_CORE | 421 | select MFD_CORE |
418 | select REGMAP_I2C | 422 | select REGMAP_I2C |
419 | help | 423 | help |
@@ -460,7 +464,7 @@ config MFD_DA9052_SPI | |||
460 | select REGMAP_SPI | 464 | select REGMAP_SPI |
461 | select REGMAP_IRQ | 465 | select REGMAP_IRQ |
462 | select PMIC_DA9052 | 466 | select PMIC_DA9052 |
463 | depends on SPI_MASTER=y | 467 | depends on SPI_MASTER=y && GENERIC_HARDIRQS |
464 | help | 468 | help |
465 | Support for the Dialog Semiconductor DA9052 PMIC | 469 | Support for the Dialog Semiconductor DA9052 PMIC |
466 | when controlled using SPI. This driver provides common support | 470 | when controlled using SPI. This driver provides common support |
@@ -472,7 +476,7 @@ config MFD_DA9052_I2C | |||
472 | select REGMAP_I2C | 476 | select REGMAP_I2C |
473 | select REGMAP_IRQ | 477 | select REGMAP_IRQ |
474 | select PMIC_DA9052 | 478 | select PMIC_DA9052 |
475 | depends on I2C=y | 479 | depends on I2C=y && GENERIC_HARDIRQS |
476 | help | 480 | help |
477 | Support for the Dialog Semiconductor DA9052 PMIC | 481 | Support for the Dialog Semiconductor DA9052 PMIC |
478 | when controlled using I2C. This driver provides common support | 482 | when controlled using I2C. This driver provides common support |
@@ -485,7 +489,7 @@ config MFD_DA9055 | |||
485 | select REGMAP_IRQ | 489 | select REGMAP_IRQ |
486 | select PMIC_DA9055 | 490 | select PMIC_DA9055 |
487 | select MFD_CORE | 491 | select MFD_CORE |
488 | depends on I2C=y | 492 | depends on I2C=y && GENERIC_HARDIRQS |
489 | help | 493 | help |
490 | Say yes here for support of Dialog Semiconductor DA9055. This is | 494 | Say yes here for support of Dialog Semiconductor DA9055. This is |
491 | a Power Management IC. This driver provides common support for | 495 | a Power Management IC. This driver provides common support for |
@@ -508,7 +512,7 @@ config PMIC_ADP5520 | |||
508 | 512 | ||
509 | config MFD_LP8788 | 513 | config MFD_LP8788 |
510 | bool "Texas Instruments LP8788 Power Management Unit Driver" | 514 | bool "Texas Instruments LP8788 Power Management Unit Driver" |
511 | depends on I2C=y | 515 | depends on I2C=y && GENERIC_HARDIRQS |
512 | select MFD_CORE | 516 | select MFD_CORE |
513 | select REGMAP_I2C | 517 | select REGMAP_I2C |
514 | select IRQ_DOMAIN | 518 | select IRQ_DOMAIN |
@@ -611,7 +615,7 @@ config MFD_ARIZONA_I2C | |||
611 | select MFD_ARIZONA | 615 | select MFD_ARIZONA |
612 | select MFD_CORE | 616 | select MFD_CORE |
613 | select REGMAP_I2C | 617 | select REGMAP_I2C |
614 | depends on I2C | 618 | depends on I2C && GENERIC_HARDIRQS |
615 | help | 619 | help |
616 | Support for the Wolfson Microelectronics Arizona platform audio SoC | 620 | Support for the Wolfson Microelectronics Arizona platform audio SoC |
617 | core functionality controlled via I2C. | 621 | core functionality controlled via I2C. |
@@ -621,7 +625,7 @@ config MFD_ARIZONA_SPI | |||
621 | select MFD_ARIZONA | 625 | select MFD_ARIZONA |
622 | select MFD_CORE | 626 | select MFD_CORE |
623 | select REGMAP_SPI | 627 | select REGMAP_SPI |
624 | depends on SPI_MASTER | 628 | depends on SPI_MASTER && GENERIC_HARDIRQS |
625 | help | 629 | help |
626 | Support for the Wolfson Microelectronics Arizona platform audio SoC | 630 | Support for the Wolfson Microelectronics Arizona platform audio SoC |
627 | core functionality controlled via I2C. | 631 | core functionality controlled via I2C. |
@@ -641,7 +645,7 @@ config MFD_WM5110 | |||
641 | config MFD_WM8400 | 645 | config MFD_WM8400 |
642 | bool "Support Wolfson Microelectronics WM8400" | 646 | bool "Support Wolfson Microelectronics WM8400" |
643 | select MFD_CORE | 647 | select MFD_CORE |
644 | depends on I2C=y | 648 | depends on I2C=y && GENERIC_HARDIRQS |
645 | select REGMAP_I2C | 649 | select REGMAP_I2C |
646 | help | 650 | help |
647 | Support for the Wolfson Microelecronics WM8400 PMIC and audio | 651 | Support for the Wolfson Microelecronics WM8400 PMIC and audio |
@@ -785,7 +789,7 @@ config MFD_MC13783 | |||
785 | 789 | ||
786 | config MFD_MC13XXX | 790 | config MFD_MC13XXX |
787 | tristate | 791 | tristate |
788 | depends on SPI_MASTER || I2C | 792 | depends on (SPI_MASTER || I2C) && GENERIC_HARDIRQS |
789 | select MFD_CORE | 793 | select MFD_CORE |
790 | select MFD_MC13783 | 794 | select MFD_MC13783 |
791 | help | 795 | help |
@@ -796,7 +800,7 @@ config MFD_MC13XXX | |||
796 | 800 | ||
797 | config MFD_MC13XXX_SPI | 801 | config MFD_MC13XXX_SPI |
798 | tristate "Freescale MC13783 and MC13892 SPI interface" | 802 | tristate "Freescale MC13783 and MC13892 SPI interface" |
799 | depends on SPI_MASTER | 803 | depends on SPI_MASTER && GENERIC_HARDIRQS |
800 | select REGMAP_SPI | 804 | select REGMAP_SPI |
801 | select MFD_MC13XXX | 805 | select MFD_MC13XXX |
802 | help | 806 | help |
@@ -804,7 +808,7 @@ config MFD_MC13XXX_SPI | |||
804 | 808 | ||
805 | config MFD_MC13XXX_I2C | 809 | config MFD_MC13XXX_I2C |
806 | tristate "Freescale MC13892 I2C interface" | 810 | tristate "Freescale MC13892 I2C interface" |
807 | depends on I2C | 811 | depends on I2C && GENERIC_HARDIRQS |
808 | select REGMAP_I2C | 812 | select REGMAP_I2C |
809 | select MFD_MC13XXX | 813 | select MFD_MC13XXX |
810 | help | 814 | help |
@@ -822,7 +826,7 @@ config ABX500_CORE | |||
822 | 826 | ||
823 | config AB3100_CORE | 827 | config AB3100_CORE |
824 | bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" | 828 | bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" |
825 | depends on I2C=y && ABX500_CORE | 829 | depends on I2C=y && ABX500_CORE && GENERIC_HARDIRQS |
826 | select MFD_CORE | 830 | select MFD_CORE |
827 | default y if ARCH_U300 | 831 | default y if ARCH_U300 |
828 | help | 832 | help |
@@ -909,7 +913,7 @@ config MFD_TIMBERDALE | |||
909 | 913 | ||
910 | config LPC_SCH | 914 | config LPC_SCH |
911 | tristate "Intel SCH LPC" | 915 | tristate "Intel SCH LPC" |
912 | depends on PCI | 916 | depends on PCI && GENERIC_HARDIRQS |
913 | select MFD_CORE | 917 | select MFD_CORE |
914 | help | 918 | help |
915 | LPC bridge function of the Intel SCH provides support for | 919 | LPC bridge function of the Intel SCH provides support for |
@@ -917,7 +921,7 @@ config LPC_SCH | |||
917 | 921 | ||
918 | config LPC_ICH | 922 | config LPC_ICH |
919 | tristate "Intel ICH LPC" | 923 | tristate "Intel ICH LPC" |
920 | depends on PCI | 924 | depends on PCI && GENERIC_HARDIRQS |
921 | select MFD_CORE | 925 | select MFD_CORE |
922 | help | 926 | help |
923 | The LPC bridge function of the Intel ICH provides support for | 927 | The LPC bridge function of the Intel ICH provides support for |
@@ -928,7 +932,7 @@ config LPC_ICH | |||
928 | config MFD_RDC321X | 932 | config MFD_RDC321X |
929 | tristate "Support for RDC-R321x southbridge" | 933 | tristate "Support for RDC-R321x southbridge" |
930 | select MFD_CORE | 934 | select MFD_CORE |
931 | depends on PCI | 935 | depends on PCI && GENERIC_HARDIRQS |
932 | help | 936 | help |
933 | Say yes here if you want to have support for the RDC R-321x SoC | 937 | Say yes here if you want to have support for the RDC R-321x SoC |
934 | southbridge which provides access to GPIOs and Watchdog using the | 938 | southbridge which provides access to GPIOs and Watchdog using the |
@@ -937,7 +941,7 @@ config MFD_RDC321X | |||
937 | config MFD_JANZ_CMODIO | 941 | config MFD_JANZ_CMODIO |
938 | tristate "Support for Janz CMOD-IO PCI MODULbus Carrier Board" | 942 | tristate "Support for Janz CMOD-IO PCI MODULbus Carrier Board" |
939 | select MFD_CORE | 943 | select MFD_CORE |
940 | depends on PCI | 944 | depends on PCI && GENERIC_HARDIRQS |
941 | help | 945 | help |
942 | This is the core driver for the Janz CMOD-IO PCI MODULbus | 946 | This is the core driver for the Janz CMOD-IO PCI MODULbus |
943 | carrier board. This device is a PCI to MODULbus bridge which may | 947 | carrier board. This device is a PCI to MODULbus bridge which may |
@@ -955,7 +959,7 @@ config MFD_JZ4740_ADC | |||
955 | 959 | ||
956 | config MFD_VX855 | 960 | config MFD_VX855 |
957 | tristate "Support for VIA VX855/VX875 integrated south bridge" | 961 | tristate "Support for VIA VX855/VX875 integrated south bridge" |
958 | depends on PCI | 962 | depends on PCI && GENERIC_HARDIRQS |
959 | select MFD_CORE | 963 | select MFD_CORE |
960 | help | 964 | help |
961 | Say yes here to enable support for various functions of the | 965 | Say yes here to enable support for various functions of the |
@@ -964,7 +968,7 @@ config MFD_VX855 | |||
964 | 968 | ||
965 | config MFD_WL1273_CORE | 969 | config MFD_WL1273_CORE |
966 | tristate "Support for TI WL1273 FM radio." | 970 | tristate "Support for TI WL1273 FM radio." |
967 | depends on I2C | 971 | depends on I2C && GENERIC_HARDIRQS |
968 | select MFD_CORE | 972 | select MFD_CORE |
969 | default n | 973 | default n |
970 | help | 974 | help |
@@ -1028,7 +1032,7 @@ config MFD_TPS65090 | |||
1028 | config MFD_AAT2870_CORE | 1032 | config MFD_AAT2870_CORE |
1029 | bool "Support for the AnalogicTech AAT2870" | 1033 | bool "Support for the AnalogicTech AAT2870" |
1030 | select MFD_CORE | 1034 | select MFD_CORE |
1031 | depends on I2C=y && GPIOLIB | 1035 | depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS |
1032 | help | 1036 | help |
1033 | If you say yes here you get support for the AAT2870. | 1037 | If you say yes here you get support for the AAT2870. |
1034 | This driver provides common support for accessing the device, | 1038 | This driver provides common support for accessing the device, |
@@ -1060,7 +1064,7 @@ config MFD_RC5T583 | |||
1060 | 1064 | ||
1061 | config MFD_STA2X11 | 1065 | config MFD_STA2X11 |
1062 | bool "STA2X11 multi function device support" | 1066 | bool "STA2X11 multi function device support" |
1063 | depends on STA2X11 | 1067 | depends on STA2X11 && GENERIC_HARDIRQS |
1064 | select MFD_CORE | 1068 | select MFD_CORE |
1065 | select REGMAP_MMIO | 1069 | select REGMAP_MMIO |
1066 | 1070 | ||
@@ -1077,7 +1081,7 @@ config MFD_PALMAS | |||
1077 | select MFD_CORE | 1081 | select MFD_CORE |
1078 | select REGMAP_I2C | 1082 | select REGMAP_I2C |
1079 | select REGMAP_IRQ | 1083 | select REGMAP_IRQ |
1080 | depends on I2C=y | 1084 | depends on I2C=y && GENERIC_HARDIRQS |
1081 | help | 1085 | help |
1082 | If you say yes here you get support for the Palmas | 1086 | If you say yes here you get support for the Palmas |
1083 | series of PMIC chips from Texas Instruments. | 1087 | series of PMIC chips from Texas Instruments. |
@@ -1085,7 +1089,7 @@ config MFD_PALMAS | |||
1085 | config MFD_VIPERBOARD | 1089 | config MFD_VIPERBOARD |
1086 | tristate "Support for Nano River Technologies Viperboard" | 1090 | tristate "Support for Nano River Technologies Viperboard" |
1087 | select MFD_CORE | 1091 | select MFD_CORE |
1088 | depends on USB | 1092 | depends on USB && GENERIC_HARDIRQS |
1089 | default n | 1093 | default n |
1090 | help | 1094 | help |
1091 | Say yes here if you want support for Nano River Technologies | 1095 | Say yes here if you want support for Nano River Technologies |
@@ -1099,7 +1103,7 @@ config MFD_VIPERBOARD | |||
1099 | config MFD_RETU | 1103 | config MFD_RETU |
1100 | tristate "Support for Retu multi-function device" | 1104 | tristate "Support for Retu multi-function device" |
1101 | select MFD_CORE | 1105 | select MFD_CORE |
1102 | depends on I2C | 1106 | depends on I2C && GENERIC_HARDIRQS |
1103 | select REGMAP_IRQ | 1107 | select REGMAP_IRQ |
1104 | help | 1108 | help |
1105 | Retu is a multi-function device found on Nokia Internet Tablets | 1109 | Retu is a multi-function device found on Nokia Internet Tablets |
@@ -1110,7 +1114,7 @@ config MFD_AS3711 | |||
1110 | select MFD_CORE | 1114 | select MFD_CORE |
1111 | select REGMAP_I2C | 1115 | select REGMAP_I2C |
1112 | select REGMAP_IRQ | 1116 | select REGMAP_IRQ |
1113 | depends on I2C=y | 1117 | depends on I2C=y && GENERIC_HARDIRQS |
1114 | help | 1118 | help |
1115 | Support for the AS3711 PMIC from AMS | 1119 | Support for the AS3711 PMIC from AMS |
1116 | 1120 | ||
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b977f8045ae..b90409c23664 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -9,7 +9,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o | |||
9 | obj-$(CONFIG_MFD_SM501) += sm501.o | 9 | obj-$(CONFIG_MFD_SM501) += sm501.o |
10 | obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o | 10 | obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o |
11 | 11 | ||
12 | rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o | 12 | rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o |
13 | obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o | 13 | obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o |
14 | 14 | ||
15 | obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o | 15 | obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 8b5d685ab980..7c84ced2e01b 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -320,6 +320,7 @@ static struct abx500_ops ab8500_ops = { | |||
320 | .mask_and_set_register = ab8500_mask_and_set_register, | 320 | .mask_and_set_register = ab8500_mask_and_set_register, |
321 | .event_registers_startup_state_get = NULL, | 321 | .event_registers_startup_state_get = NULL, |
322 | .startup_irq_enabled = NULL, | 322 | .startup_irq_enabled = NULL, |
323 | .dump_all_banks = ab8500_dump_all_banks, | ||
323 | }; | 324 | }; |
324 | 325 | ||
325 | static void ab8500_irq_lock(struct irq_data *data) | 326 | static void ab8500_irq_lock(struct irq_data *data) |
@@ -368,16 +369,48 @@ static void ab8500_irq_mask(struct irq_data *data) | |||
368 | int mask = 1 << (offset % 8); | 369 | int mask = 1 << (offset % 8); |
369 | 370 | ||
370 | ab8500->mask[index] |= mask; | 371 | ab8500->mask[index] |= mask; |
372 | |||
373 | /* The AB8500 GPIOs have two interrupts each (rising & falling). */ | ||
374 | if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) | ||
375 | ab8500->mask[index + 2] |= mask; | ||
376 | if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) | ||
377 | ab8500->mask[index + 1] |= mask; | ||
378 | if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) | ||
379 | /* Here the falling IRQ is one bit lower */ | ||
380 | ab8500->mask[index] |= (mask << 1); | ||
371 | } | 381 | } |
372 | 382 | ||
373 | static void ab8500_irq_unmask(struct irq_data *data) | 383 | static void ab8500_irq_unmask(struct irq_data *data) |
374 | { | 384 | { |
375 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); | 385 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); |
386 | unsigned int type = irqd_get_trigger_type(data); | ||
376 | int offset = data->hwirq; | 387 | int offset = data->hwirq; |
377 | int index = offset / 8; | 388 | int index = offset / 8; |
378 | int mask = 1 << (offset % 8); | 389 | int mask = 1 << (offset % 8); |
379 | 390 | ||
380 | ab8500->mask[index] &= ~mask; | 391 | if (type & IRQ_TYPE_EDGE_RISING) |
392 | ab8500->mask[index] &= ~mask; | ||
393 | |||
394 | /* The AB8500 GPIOs have two interrupts each (rising & falling). */ | ||
395 | if (type & IRQ_TYPE_EDGE_FALLING) { | ||
396 | if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) | ||
397 | ab8500->mask[index + 2] &= ~mask; | ||
398 | else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) | ||
399 | ab8500->mask[index + 1] &= ~mask; | ||
400 | else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) | ||
401 | /* Here the falling IRQ is one bit lower */ | ||
402 | ab8500->mask[index] &= ~(mask << 1); | ||
403 | else | ||
404 | ab8500->mask[index] &= ~mask; | ||
405 | } else { | ||
406 | /* Satisfies the case where type is not set. */ | ||
407 | ab8500->mask[index] &= ~mask; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) | ||
412 | { | ||
413 | return 0; | ||
381 | } | 414 | } |
382 | 415 | ||
383 | static struct irq_chip ab8500_irq_chip = { | 416 | static struct irq_chip ab8500_irq_chip = { |
@@ -387,6 +420,7 @@ static struct irq_chip ab8500_irq_chip = { | |||
387 | .irq_mask = ab8500_irq_mask, | 420 | .irq_mask = ab8500_irq_mask, |
388 | .irq_disable = ab8500_irq_mask, | 421 | .irq_disable = ab8500_irq_mask, |
389 | .irq_unmask = ab8500_irq_unmask, | 422 | .irq_unmask = ab8500_irq_unmask, |
423 | .irq_set_type = ab8500_irq_set_type, | ||
390 | }; | 424 | }; |
391 | 425 | ||
392 | static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, | 426 | static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, |
@@ -411,6 +445,19 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, | |||
411 | line = (i << 3) + int_bit; | 445 | line = (i << 3) + int_bit; |
412 | latch_val &= ~(1 << int_bit); | 446 | latch_val &= ~(1 << int_bit); |
413 | 447 | ||
448 | /* | ||
449 | * This handles the falling edge hwirqs from the GPIO | ||
450 | * lines. Route them back to the line registered for the | ||
451 | * rising IRQ, as this is merely a flag for the same IRQ | ||
452 | * in linux terms. | ||
453 | */ | ||
454 | if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) | ||
455 | line -= 16; | ||
456 | if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) | ||
457 | line -= 8; | ||
458 | if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) | ||
459 | line += 1; | ||
460 | |||
414 | handle_nested_irq(ab8500->irq_base + line); | 461 | handle_nested_irq(ab8500->irq_base + line); |
415 | } while (latch_val); | 462 | } while (latch_val); |
416 | 463 | ||
@@ -521,6 +568,7 @@ static irqreturn_t ab8500_irq(int irq, void *dev) | |||
521 | int virq = ab8500_irq_get_virq(ab8500, line); | 568 | int virq = ab8500_irq_get_virq(ab8500, line); |
522 | 569 | ||
523 | handle_nested_irq(virq); | 570 | handle_nested_irq(virq); |
571 | ab8500_debug_register_interrupt(line); | ||
524 | value &= ~(1 << bit); | 572 | value &= ~(1 << bit); |
525 | 573 | ||
526 | } while (value); | 574 | } while (value); |
@@ -929,7 +977,7 @@ static struct resource ab8505_iddet_resources[] = { | |||
929 | 977 | ||
930 | static struct resource ab8500_temp_resources[] = { | 978 | static struct resource ab8500_temp_resources[] = { |
931 | { | 979 | { |
932 | .name = "AB8500_TEMP_WARM", | 980 | .name = "ABX500_TEMP_WARM", |
933 | .start = AB8500_INT_TEMP_WARM, | 981 | .start = AB8500_INT_TEMP_WARM, |
934 | .end = AB8500_INT_TEMP_WARM, | 982 | .end = AB8500_INT_TEMP_WARM, |
935 | .flags = IORESOURCE_IRQ, | 983 | .flags = IORESOURCE_IRQ, |
@@ -1005,8 +1053,8 @@ static struct mfd_cell abx500_common_devs[] = { | |||
1005 | .of_compatible = "stericsson,ab8500-denc", | 1053 | .of_compatible = "stericsson,ab8500-denc", |
1006 | }, | 1054 | }, |
1007 | { | 1055 | { |
1008 | .name = "ab8500-temp", | 1056 | .name = "abx500-temp", |
1009 | .of_compatible = "stericsson,ab8500-temp", | 1057 | .of_compatible = "stericsson,abx500-temp", |
1010 | .num_resources = ARRAY_SIZE(ab8500_temp_resources), | 1058 | .num_resources = ARRAY_SIZE(ab8500_temp_resources), |
1011 | .resources = ab8500_temp_resources, | 1059 | .resources = ab8500_temp_resources, |
1012 | }, | 1060 | }, |
@@ -1049,7 +1097,7 @@ static struct mfd_cell ab8500_bm_devs[] = { | |||
1049 | 1097 | ||
1050 | static struct mfd_cell ab8500_devs[] = { | 1098 | static struct mfd_cell ab8500_devs[] = { |
1051 | { | 1099 | { |
1052 | .name = "ab8500-gpio", | 1100 | .name = "pinctrl-ab8500", |
1053 | .of_compatible = "stericsson,ab8500-gpio", | 1101 | .of_compatible = "stericsson,ab8500-gpio", |
1054 | }, | 1102 | }, |
1055 | { | 1103 | { |
@@ -1066,7 +1114,8 @@ static struct mfd_cell ab8500_devs[] = { | |||
1066 | 1114 | ||
1067 | static struct mfd_cell ab9540_devs[] = { | 1115 | static struct mfd_cell ab9540_devs[] = { |
1068 | { | 1116 | { |
1069 | .name = "ab8500-gpio", | 1117 | .name = "pinctrl-ab9540", |
1118 | .of_compatible = "stericsson,ab9540-gpio", | ||
1070 | }, | 1119 | }, |
1071 | { | 1120 | { |
1072 | .name = "ab9540-usb", | 1121 | .name = "ab9540-usb", |
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 5a8e707bc038..45fe3c50eb03 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c | |||
@@ -4,6 +4,72 @@ | |||
4 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson. | 4 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson. |
5 | * License Terms: GNU General Public License v2 | 5 | * License Terms: GNU General Public License v2 |
6 | */ | 6 | */ |
7 | /* | ||
8 | * AB8500 register access | ||
9 | * ====================== | ||
10 | * | ||
11 | * read: | ||
12 | * # echo BANK > <debugfs>/ab8500/register-bank | ||
13 | * # echo ADDR > <debugfs>/ab8500/register-address | ||
14 | * # cat <debugfs>/ab8500/register-value | ||
15 | * | ||
16 | * write: | ||
17 | * # echo BANK > <debugfs>/ab8500/register-bank | ||
18 | * # echo ADDR > <debugfs>/ab8500/register-address | ||
19 | * # echo VALUE > <debugfs>/ab8500/register-value | ||
20 | * | ||
21 | * read all registers from a bank: | ||
22 | * # echo BANK > <debugfs>/ab8500/register-bank | ||
23 | * # cat <debugfs>/ab8500/all-bank-register | ||
24 | * | ||
25 | * BANK target AB8500 register bank | ||
26 | * ADDR target AB8500 register address | ||
27 | * VALUE decimal or 0x-prefixed hexadecimal | ||
28 | * | ||
29 | * | ||
30 | * User Space notification on AB8500 IRQ | ||
31 | * ===================================== | ||
32 | * | ||
33 | * Allows user space entity to be notified when target AB8500 IRQ occurs. | ||
34 | * When subscribed, a sysfs entry is created in ab8500.i2c platform device. | ||
35 | * One can pool this file to get target IRQ occurence information. | ||
36 | * | ||
37 | * subscribe to an AB8500 IRQ: | ||
38 | * # echo IRQ > <debugfs>/ab8500/irq-subscribe | ||
39 | * | ||
40 | * unsubscribe from an AB8500 IRQ: | ||
41 | * # echo IRQ > <debugfs>/ab8500/irq-unsubscribe | ||
42 | * | ||
43 | * | ||
44 | * AB8500 register formated read/write access | ||
45 | * ========================================== | ||
46 | * | ||
47 | * Read: read data, data>>SHIFT, data&=MASK, output data | ||
48 | * [0xABCDEF98] shift=12 mask=0xFFF => 0x00000CDE | ||
49 | * Write: read data, data &= ~(MASK<<SHIFT), data |= (VALUE<<SHIFT), write data | ||
50 | * [0xABCDEF98] shift=12 mask=0xFFF value=0x123 => [0xAB123F98] | ||
51 | * | ||
52 | * Usage: | ||
53 | * # echo "CMD [OPTIONS] BANK ADRESS [VALUE]" > $debugfs/ab8500/hwreg | ||
54 | * | ||
55 | * CMD read read access | ||
56 | * write write access | ||
57 | * | ||
58 | * BANK target reg bank | ||
59 | * ADDRESS target reg address | ||
60 | * VALUE (write) value to be updated | ||
61 | * | ||
62 | * OPTIONS | ||
63 | * -d|-dec (read) output in decimal | ||
64 | * -h|-hexa (read) output in 0x-hexa (default) | ||
65 | * -l|-w|-b 32bit (default), 16bit or 8bit reg access | ||
66 | * -m|-mask MASK 0x-hexa mask (default 0xFFFFFFFF) | ||
67 | * -s|-shift SHIFT bit shift value (read:left, write:right) | ||
68 | * -o|-offset OFFSET address offset to add to ADDRESS value | ||
69 | * | ||
70 | * Warning: bit shift operation is applied to bit-mask. | ||
71 | * Warning: bit shift direction depends on read or right command. | ||
72 | */ | ||
7 | 73 | ||
8 | #include <linux/seq_file.h> | 74 | #include <linux/seq_file.h> |
9 | #include <linux/uaccess.h> | 75 | #include <linux/uaccess.h> |
@@ -11,13 +77,30 @@ | |||
11 | #include <linux/module.h> | 77 | #include <linux/module.h> |
12 | #include <linux/debugfs.h> | 78 | #include <linux/debugfs.h> |
13 | #include <linux/platform_device.h> | 79 | #include <linux/platform_device.h> |
80 | #include <linux/interrupt.h> | ||
81 | #include <linux/kobject.h> | ||
82 | #include <linux/slab.h> | ||
14 | 83 | ||
15 | #include <linux/mfd/abx500.h> | 84 | #include <linux/mfd/abx500.h> |
16 | #include <linux/mfd/abx500/ab8500.h> | 85 | #include <linux/mfd/abx500/ab8500.h> |
86 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
87 | |||
88 | #ifdef CONFIG_DEBUG_FS | ||
89 | #include <linux/string.h> | ||
90 | #include <linux/ctype.h> | ||
91 | #endif | ||
17 | 92 | ||
18 | static u32 debug_bank; | 93 | static u32 debug_bank; |
19 | static u32 debug_address; | 94 | static u32 debug_address; |
20 | 95 | ||
96 | static int irq_first; | ||
97 | static int irq_last; | ||
98 | static u32 *irq_count; | ||
99 | static int num_irqs; | ||
100 | |||
101 | static struct device_attribute **dev_attr; | ||
102 | static char **event_name; | ||
103 | |||
21 | /** | 104 | /** |
22 | * struct ab8500_reg_range | 105 | * struct ab8500_reg_range |
23 | * @first: the first address of the range | 106 | * @first: the first address of the range |
@@ -42,15 +125,35 @@ struct ab8500_prcmu_ranges { | |||
42 | const struct ab8500_reg_range *range; | 125 | const struct ab8500_reg_range *range; |
43 | }; | 126 | }; |
44 | 127 | ||
128 | /* hwreg- "mask" and "shift" entries ressources */ | ||
129 | struct hwreg_cfg { | ||
130 | u32 bank; /* target bank */ | ||
131 | u32 addr; /* target address */ | ||
132 | uint fmt; /* format */ | ||
133 | uint mask; /* read/write mask, applied before any bit shift */ | ||
134 | int shift; /* bit shift (read:right shift, write:left shift */ | ||
135 | }; | ||
136 | /* fmt bit #0: 0=hexa, 1=dec */ | ||
137 | #define REG_FMT_DEC(c) ((c)->fmt & 0x1) | ||
138 | #define REG_FMT_HEX(c) (!REG_FMT_DEC(c)) | ||
139 | |||
140 | static struct hwreg_cfg hwreg_cfg = { | ||
141 | .addr = 0, /* default: invalid phys addr */ | ||
142 | .fmt = 0, /* default: 32bit access, hex output */ | ||
143 | .mask = 0xFFFFFFFF, /* default: no mask */ | ||
144 | .shift = 0, /* default: no bit shift */ | ||
145 | }; | ||
146 | |||
45 | #define AB8500_NAME_STRING "ab8500" | 147 | #define AB8500_NAME_STRING "ab8500" |
46 | #define AB8500_NUM_BANKS 22 | 148 | #define AB8500_ADC_NAME_STRING "gpadc" |
149 | #define AB8500_NUM_BANKS 24 | ||
47 | 150 | ||
48 | #define AB8500_REV_REG 0x80 | 151 | #define AB8500_REV_REG 0x80 |
49 | 152 | ||
50 | static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | 153 | static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { |
51 | [0x0] = { | 154 | [0x0] = { |
52 | .num_ranges = 0, | 155 | .num_ranges = 0, |
53 | .range = 0, | 156 | .range = NULL, |
54 | }, | 157 | }, |
55 | [AB8500_SYS_CTRL1_BLOCK] = { | 158 | [AB8500_SYS_CTRL1_BLOCK] = { |
56 | .num_ranges = 3, | 159 | .num_ranges = 3, |
@@ -215,7 +318,7 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | |||
215 | }, | 318 | }, |
216 | }, | 319 | }, |
217 | [AB8500_CHARGER] = { | 320 | [AB8500_CHARGER] = { |
218 | .num_ranges = 8, | 321 | .num_ranges = 9, |
219 | .range = (struct ab8500_reg_range[]) { | 322 | .range = (struct ab8500_reg_range[]) { |
220 | { | 323 | { |
221 | .first = 0x00, | 324 | .first = 0x00, |
@@ -249,6 +352,10 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | |||
249 | .first = 0xC0, | 352 | .first = 0xC0, |
250 | .last = 0xC2, | 353 | .last = 0xC2, |
251 | }, | 354 | }, |
355 | { | ||
356 | .first = 0xf5, | ||
357 | .last = 0xf6, | ||
358 | }, | ||
252 | }, | 359 | }, |
253 | }, | 360 | }, |
254 | [AB8500_GAS_GAUGE] = { | 361 | [AB8500_GAS_GAUGE] = { |
@@ -268,6 +375,24 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | |||
268 | }, | 375 | }, |
269 | }, | 376 | }, |
270 | }, | 377 | }, |
378 | [AB8500_DEVELOPMENT] = { | ||
379 | .num_ranges = 1, | ||
380 | .range = (struct ab8500_reg_range[]) { | ||
381 | { | ||
382 | .first = 0x00, | ||
383 | .last = 0x00, | ||
384 | }, | ||
385 | }, | ||
386 | }, | ||
387 | [AB8500_DEBUG] = { | ||
388 | .num_ranges = 1, | ||
389 | .range = (struct ab8500_reg_range[]) { | ||
390 | { | ||
391 | .first = 0x05, | ||
392 | .last = 0x07, | ||
393 | }, | ||
394 | }, | ||
395 | }, | ||
271 | [AB8500_AUDIO] = { | 396 | [AB8500_AUDIO] = { |
272 | .num_ranges = 1, | 397 | .num_ranges = 1, |
273 | .range = (struct ab8500_reg_range[]) { | 398 | .range = (struct ab8500_reg_range[]) { |
@@ -354,15 +479,30 @@ static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { | |||
354 | }, | 479 | }, |
355 | }; | 480 | }; |
356 | 481 | ||
357 | static int ab8500_registers_print(struct seq_file *s, void *p) | 482 | static irqreturn_t ab8500_debug_handler(int irq, void *data) |
358 | { | 483 | { |
359 | struct device *dev = s->private; | 484 | char buf[16]; |
360 | unsigned int i; | 485 | struct kobject *kobj = (struct kobject *)data; |
361 | u32 bank = debug_bank; | 486 | unsigned int irq_abb = irq - irq_first; |
362 | 487 | ||
363 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); | 488 | if (irq_abb < num_irqs) |
489 | irq_count[irq_abb]++; | ||
490 | /* | ||
491 | * This makes it possible to use poll for events (POLLPRI | POLLERR) | ||
492 | * from userspace on sysfs file named <irq-nr> | ||
493 | */ | ||
494 | sprintf(buf, "%d", irq); | ||
495 | sysfs_notify(kobj, NULL, buf); | ||
496 | |||
497 | return IRQ_HANDLED; | ||
498 | } | ||
499 | |||
500 | /* Prints to seq_file or log_buf */ | ||
501 | static int ab8500_registers_print(struct device *dev, u32 bank, | ||
502 | struct seq_file *s) | ||
503 | { | ||
504 | unsigned int i; | ||
364 | 505 | ||
365 | seq_printf(s, " bank %u:\n", bank); | ||
366 | for (i = 0; i < debug_ranges[bank].num_ranges; i++) { | 506 | for (i = 0; i < debug_ranges[bank].num_ranges; i++) { |
367 | u32 reg; | 507 | u32 reg; |
368 | 508 | ||
@@ -379,22 +519,42 @@ static int ab8500_registers_print(struct seq_file *s, void *p) | |||
379 | return err; | 519 | return err; |
380 | } | 520 | } |
381 | 521 | ||
382 | err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n", bank, | 522 | if (s) { |
383 | reg, value); | 523 | err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n", |
384 | if (err < 0) { | 524 | bank, reg, value); |
385 | dev_err(dev, "seq_printf overflow\n"); | 525 | if (err < 0) { |
386 | /* Error is not returned here since | 526 | dev_err(dev, |
387 | * the output is wanted in any case */ | 527 | "seq_printf overflow bank=%d reg=%d\n", |
388 | return 0; | 528 | bank, reg); |
529 | /* Error is not returned here since | ||
530 | * the output is wanted in any case */ | ||
531 | return 0; | ||
532 | } | ||
533 | } else { | ||
534 | printk(KERN_INFO" [%u/0x%02X]: 0x%02X\n", bank, | ||
535 | reg, value); | ||
389 | } | 536 | } |
390 | } | 537 | } |
391 | } | 538 | } |
392 | return 0; | 539 | return 0; |
393 | } | 540 | } |
394 | 541 | ||
542 | static int ab8500_print_bank_registers(struct seq_file *s, void *p) | ||
543 | { | ||
544 | struct device *dev = s->private; | ||
545 | u32 bank = debug_bank; | ||
546 | |||
547 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); | ||
548 | |||
549 | seq_printf(s, " bank %u:\n", bank); | ||
550 | |||
551 | ab8500_registers_print(dev, bank, s); | ||
552 | return 0; | ||
553 | } | ||
554 | |||
395 | static int ab8500_registers_open(struct inode *inode, struct file *file) | 555 | static int ab8500_registers_open(struct inode *inode, struct file *file) |
396 | { | 556 | { |
397 | return single_open(file, ab8500_registers_print, inode->i_private); | 557 | return single_open(file, ab8500_print_bank_registers, inode->i_private); |
398 | } | 558 | } |
399 | 559 | ||
400 | static const struct file_operations ab8500_registers_fops = { | 560 | static const struct file_operations ab8500_registers_fops = { |
@@ -405,6 +565,64 @@ static const struct file_operations ab8500_registers_fops = { | |||
405 | .owner = THIS_MODULE, | 565 | .owner = THIS_MODULE, |
406 | }; | 566 | }; |
407 | 567 | ||
568 | static int ab8500_print_all_banks(struct seq_file *s, void *p) | ||
569 | { | ||
570 | struct device *dev = s->private; | ||
571 | unsigned int i; | ||
572 | int err; | ||
573 | |||
574 | seq_printf(s, AB8500_NAME_STRING " register values:\n"); | ||
575 | |||
576 | for (i = 1; i < AB8500_NUM_BANKS; i++) { | ||
577 | err = seq_printf(s, " bank %u:\n", i); | ||
578 | if (err < 0) | ||
579 | dev_err(dev, "seq_printf overflow, bank=%d\n", i); | ||
580 | |||
581 | ab8500_registers_print(dev, i, s); | ||
582 | } | ||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | /* Dump registers to kernel log */ | ||
587 | void ab8500_dump_all_banks(struct device *dev) | ||
588 | { | ||
589 | unsigned int i; | ||
590 | |||
591 | printk(KERN_INFO"ab8500 register values:\n"); | ||
592 | |||
593 | for (i = 1; i < AB8500_NUM_BANKS; i++) { | ||
594 | printk(KERN_INFO" bank %u:\n", i); | ||
595 | ab8500_registers_print(dev, i, NULL); | ||
596 | } | ||
597 | } | ||
598 | |||
599 | static int ab8500_all_banks_open(struct inode *inode, struct file *file) | ||
600 | { | ||
601 | struct seq_file *s; | ||
602 | int err; | ||
603 | |||
604 | err = single_open(file, ab8500_print_all_banks, inode->i_private); | ||
605 | if (!err) { | ||
606 | /* Default buf size in seq_read is not enough */ | ||
607 | s = (struct seq_file *)file->private_data; | ||
608 | s->size = (PAGE_SIZE * 2); | ||
609 | s->buf = kmalloc(s->size, GFP_KERNEL); | ||
610 | if (!s->buf) { | ||
611 | single_release(inode, file); | ||
612 | err = -ENOMEM; | ||
613 | } | ||
614 | } | ||
615 | return err; | ||
616 | } | ||
617 | |||
618 | static const struct file_operations ab8500_all_banks_fops = { | ||
619 | .open = ab8500_all_banks_open, | ||
620 | .read = seq_read, | ||
621 | .llseek = seq_lseek, | ||
622 | .release = single_release, | ||
623 | .owner = THIS_MODULE, | ||
624 | }; | ||
625 | |||
408 | static int ab8500_bank_print(struct seq_file *s, void *p) | 626 | static int ab8500_bank_print(struct seq_file *s, void *p) |
409 | { | 627 | { |
410 | return seq_printf(s, "%d\n", debug_bank); | 628 | return seq_printf(s, "%d\n", debug_bank); |
@@ -519,6 +737,761 @@ static ssize_t ab8500_val_write(struct file *file, | |||
519 | return count; | 737 | return count; |
520 | } | 738 | } |
521 | 739 | ||
740 | /* | ||
741 | * Interrupt status | ||
742 | */ | ||
743 | static u32 num_interrupts[AB8500_MAX_NR_IRQS]; | ||
744 | static int num_interrupt_lines; | ||
745 | |||
746 | void ab8500_debug_register_interrupt(int line) | ||
747 | { | ||
748 | if (line < num_interrupt_lines) | ||
749 | num_interrupts[line]++; | ||
750 | } | ||
751 | |||
752 | static int ab8500_interrupts_print(struct seq_file *s, void *p) | ||
753 | { | ||
754 | int line; | ||
755 | |||
756 | seq_printf(s, "irq: number of\n"); | ||
757 | |||
758 | for (line = 0; line < num_interrupt_lines; line++) | ||
759 | seq_printf(s, "%3i: %6i\n", line, num_interrupts[line]); | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int ab8500_interrupts_open(struct inode *inode, struct file *file) | ||
765 | { | ||
766 | return single_open(file, ab8500_interrupts_print, inode->i_private); | ||
767 | } | ||
768 | |||
769 | /* | ||
770 | * - HWREG DB8500 formated routines | ||
771 | */ | ||
772 | static int ab8500_hwreg_print(struct seq_file *s, void *d) | ||
773 | { | ||
774 | struct device *dev = s->private; | ||
775 | int ret; | ||
776 | u8 regvalue; | ||
777 | |||
778 | ret = abx500_get_register_interruptible(dev, | ||
779 | (u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, ®value); | ||
780 | if (ret < 0) { | ||
781 | dev_err(dev, "abx500_get_reg fail %d, %d\n", | ||
782 | ret, __LINE__); | ||
783 | return -EINVAL; | ||
784 | } | ||
785 | |||
786 | if (hwreg_cfg.shift >= 0) | ||
787 | regvalue >>= hwreg_cfg.shift; | ||
788 | else | ||
789 | regvalue <<= -hwreg_cfg.shift; | ||
790 | regvalue &= hwreg_cfg.mask; | ||
791 | |||
792 | if (REG_FMT_DEC(&hwreg_cfg)) | ||
793 | seq_printf(s, "%d\n", regvalue); | ||
794 | else | ||
795 | seq_printf(s, "0x%02X\n", regvalue); | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | static int ab8500_hwreg_open(struct inode *inode, struct file *file) | ||
800 | { | ||
801 | return single_open(file, ab8500_hwreg_print, inode->i_private); | ||
802 | } | ||
803 | |||
804 | static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) | ||
805 | { | ||
806 | int bat_ctrl_raw; | ||
807 | int bat_ctrl_convert; | ||
808 | struct ab8500_gpadc *gpadc; | ||
809 | |||
810 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
811 | bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL); | ||
812 | bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, | ||
813 | BAT_CTRL, bat_ctrl_raw); | ||
814 | |||
815 | return seq_printf(s, "%d,0x%X\n", | ||
816 | bat_ctrl_convert, bat_ctrl_raw); | ||
817 | } | ||
818 | |||
819 | static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file) | ||
820 | { | ||
821 | return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private); | ||
822 | } | ||
823 | |||
824 | static const struct file_operations ab8500_gpadc_bat_ctrl_fops = { | ||
825 | .open = ab8500_gpadc_bat_ctrl_open, | ||
826 | .read = seq_read, | ||
827 | .llseek = seq_lseek, | ||
828 | .release = single_release, | ||
829 | .owner = THIS_MODULE, | ||
830 | }; | ||
831 | |||
832 | static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p) | ||
833 | { | ||
834 | int btemp_ball_raw; | ||
835 | int btemp_ball_convert; | ||
836 | struct ab8500_gpadc *gpadc; | ||
837 | |||
838 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
839 | btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL); | ||
840 | btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, | ||
841 | btemp_ball_raw); | ||
842 | |||
843 | return seq_printf(s, | ||
844 | "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); | ||
845 | } | ||
846 | |||
847 | static int ab8500_gpadc_btemp_ball_open(struct inode *inode, | ||
848 | struct file *file) | ||
849 | { | ||
850 | return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private); | ||
851 | } | ||
852 | |||
853 | static const struct file_operations ab8500_gpadc_btemp_ball_fops = { | ||
854 | .open = ab8500_gpadc_btemp_ball_open, | ||
855 | .read = seq_read, | ||
856 | .llseek = seq_lseek, | ||
857 | .release = single_release, | ||
858 | .owner = THIS_MODULE, | ||
859 | }; | ||
860 | |||
861 | static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p) | ||
862 | { | ||
863 | int main_charger_v_raw; | ||
864 | int main_charger_v_convert; | ||
865 | struct ab8500_gpadc *gpadc; | ||
866 | |||
867 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
868 | main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V); | ||
869 | main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, | ||
870 | MAIN_CHARGER_V, main_charger_v_raw); | ||
871 | |||
872 | return seq_printf(s, "%d,0x%X\n", | ||
873 | main_charger_v_convert, main_charger_v_raw); | ||
874 | } | ||
875 | |||
876 | static int ab8500_gpadc_main_charger_v_open(struct inode *inode, | ||
877 | struct file *file) | ||
878 | { | ||
879 | return single_open(file, ab8500_gpadc_main_charger_v_print, | ||
880 | inode->i_private); | ||
881 | } | ||
882 | |||
883 | static const struct file_operations ab8500_gpadc_main_charger_v_fops = { | ||
884 | .open = ab8500_gpadc_main_charger_v_open, | ||
885 | .read = seq_read, | ||
886 | .llseek = seq_lseek, | ||
887 | .release = single_release, | ||
888 | .owner = THIS_MODULE, | ||
889 | }; | ||
890 | |||
891 | static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p) | ||
892 | { | ||
893 | int acc_detect1_raw; | ||
894 | int acc_detect1_convert; | ||
895 | struct ab8500_gpadc *gpadc; | ||
896 | |||
897 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
898 | acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1); | ||
899 | acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, | ||
900 | acc_detect1_raw); | ||
901 | |||
902 | return seq_printf(s, "%d,0x%X\n", | ||
903 | acc_detect1_convert, acc_detect1_raw); | ||
904 | } | ||
905 | |||
906 | static int ab8500_gpadc_acc_detect1_open(struct inode *inode, | ||
907 | struct file *file) | ||
908 | { | ||
909 | return single_open(file, ab8500_gpadc_acc_detect1_print, | ||
910 | inode->i_private); | ||
911 | } | ||
912 | |||
913 | static const struct file_operations ab8500_gpadc_acc_detect1_fops = { | ||
914 | .open = ab8500_gpadc_acc_detect1_open, | ||
915 | .read = seq_read, | ||
916 | .llseek = seq_lseek, | ||
917 | .release = single_release, | ||
918 | .owner = THIS_MODULE, | ||
919 | }; | ||
920 | |||
921 | static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p) | ||
922 | { | ||
923 | int acc_detect2_raw; | ||
924 | int acc_detect2_convert; | ||
925 | struct ab8500_gpadc *gpadc; | ||
926 | |||
927 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
928 | acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2); | ||
929 | acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, | ||
930 | ACC_DETECT2, acc_detect2_raw); | ||
931 | |||
932 | return seq_printf(s, "%d,0x%X\n", | ||
933 | acc_detect2_convert, acc_detect2_raw); | ||
934 | } | ||
935 | |||
936 | static int ab8500_gpadc_acc_detect2_open(struct inode *inode, | ||
937 | struct file *file) | ||
938 | { | ||
939 | return single_open(file, ab8500_gpadc_acc_detect2_print, | ||
940 | inode->i_private); | ||
941 | } | ||
942 | |||
943 | static const struct file_operations ab8500_gpadc_acc_detect2_fops = { | ||
944 | .open = ab8500_gpadc_acc_detect2_open, | ||
945 | .read = seq_read, | ||
946 | .llseek = seq_lseek, | ||
947 | .release = single_release, | ||
948 | .owner = THIS_MODULE, | ||
949 | }; | ||
950 | |||
951 | static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p) | ||
952 | { | ||
953 | int aux1_raw; | ||
954 | int aux1_convert; | ||
955 | struct ab8500_gpadc *gpadc; | ||
956 | |||
957 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
958 | aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1); | ||
959 | aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, | ||
960 | aux1_raw); | ||
961 | |||
962 | return seq_printf(s, "%d,0x%X\n", | ||
963 | aux1_convert, aux1_raw); | ||
964 | } | ||
965 | |||
966 | static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file) | ||
967 | { | ||
968 | return single_open(file, ab8500_gpadc_aux1_print, inode->i_private); | ||
969 | } | ||
970 | |||
971 | static const struct file_operations ab8500_gpadc_aux1_fops = { | ||
972 | .open = ab8500_gpadc_aux1_open, | ||
973 | .read = seq_read, | ||
974 | .llseek = seq_lseek, | ||
975 | .release = single_release, | ||
976 | .owner = THIS_MODULE, | ||
977 | }; | ||
978 | |||
979 | static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p) | ||
980 | { | ||
981 | int aux2_raw; | ||
982 | int aux2_convert; | ||
983 | struct ab8500_gpadc *gpadc; | ||
984 | |||
985 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
986 | aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2); | ||
987 | aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, | ||
988 | aux2_raw); | ||
989 | |||
990 | return seq_printf(s, "%d,0x%X\n", | ||
991 | aux2_convert, aux2_raw); | ||
992 | } | ||
993 | |||
994 | static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file) | ||
995 | { | ||
996 | return single_open(file, ab8500_gpadc_aux2_print, inode->i_private); | ||
997 | } | ||
998 | |||
999 | static const struct file_operations ab8500_gpadc_aux2_fops = { | ||
1000 | .open = ab8500_gpadc_aux2_open, | ||
1001 | .read = seq_read, | ||
1002 | .llseek = seq_lseek, | ||
1003 | .release = single_release, | ||
1004 | .owner = THIS_MODULE, | ||
1005 | }; | ||
1006 | |||
1007 | static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p) | ||
1008 | { | ||
1009 | int main_bat_v_raw; | ||
1010 | int main_bat_v_convert; | ||
1011 | struct ab8500_gpadc *gpadc; | ||
1012 | |||
1013 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
1014 | main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V); | ||
1015 | main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, | ||
1016 | main_bat_v_raw); | ||
1017 | |||
1018 | return seq_printf(s, "%d,0x%X\n", | ||
1019 | main_bat_v_convert, main_bat_v_raw); | ||
1020 | } | ||
1021 | |||
1022 | static int ab8500_gpadc_main_bat_v_open(struct inode *inode, | ||
1023 | struct file *file) | ||
1024 | { | ||
1025 | return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private); | ||
1026 | } | ||
1027 | |||
1028 | static const struct file_operations ab8500_gpadc_main_bat_v_fops = { | ||
1029 | .open = ab8500_gpadc_main_bat_v_open, | ||
1030 | .read = seq_read, | ||
1031 | .llseek = seq_lseek, | ||
1032 | .release = single_release, | ||
1033 | .owner = THIS_MODULE, | ||
1034 | }; | ||
1035 | |||
1036 | static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p) | ||
1037 | { | ||
1038 | int vbus_v_raw; | ||
1039 | int vbus_v_convert; | ||
1040 | struct ab8500_gpadc *gpadc; | ||
1041 | |||
1042 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
1043 | vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V); | ||
1044 | vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, | ||
1045 | vbus_v_raw); | ||
1046 | |||
1047 | return seq_printf(s, "%d,0x%X\n", | ||
1048 | vbus_v_convert, vbus_v_raw); | ||
1049 | } | ||
1050 | |||
1051 | static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file) | ||
1052 | { | ||
1053 | return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private); | ||
1054 | } | ||
1055 | |||
1056 | static const struct file_operations ab8500_gpadc_vbus_v_fops = { | ||
1057 | .open = ab8500_gpadc_vbus_v_open, | ||
1058 | .read = seq_read, | ||
1059 | .llseek = seq_lseek, | ||
1060 | .release = single_release, | ||
1061 | .owner = THIS_MODULE, | ||
1062 | }; | ||
1063 | |||
1064 | static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p) | ||
1065 | { | ||
1066 | int main_charger_c_raw; | ||
1067 | int main_charger_c_convert; | ||
1068 | struct ab8500_gpadc *gpadc; | ||
1069 | |||
1070 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
1071 | main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C); | ||
1072 | main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, | ||
1073 | MAIN_CHARGER_C, main_charger_c_raw); | ||
1074 | |||
1075 | return seq_printf(s, "%d,0x%X\n", | ||
1076 | main_charger_c_convert, main_charger_c_raw); | ||
1077 | } | ||
1078 | |||
1079 | static int ab8500_gpadc_main_charger_c_open(struct inode *inode, | ||
1080 | struct file *file) | ||
1081 | { | ||
1082 | return single_open(file, ab8500_gpadc_main_charger_c_print, | ||
1083 | inode->i_private); | ||
1084 | } | ||
1085 | |||
1086 | static const struct file_operations ab8500_gpadc_main_charger_c_fops = { | ||
1087 | .open = ab8500_gpadc_main_charger_c_open, | ||
1088 | .read = seq_read, | ||
1089 | .llseek = seq_lseek, | ||
1090 | .release = single_release, | ||
1091 | .owner = THIS_MODULE, | ||
1092 | }; | ||
1093 | |||
1094 | static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p) | ||
1095 | { | ||
1096 | int usb_charger_c_raw; | ||
1097 | int usb_charger_c_convert; | ||
1098 | struct ab8500_gpadc *gpadc; | ||
1099 | |||
1100 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
1101 | usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C); | ||
1102 | usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, | ||
1103 | USB_CHARGER_C, usb_charger_c_raw); | ||
1104 | |||
1105 | return seq_printf(s, "%d,0x%X\n", | ||
1106 | usb_charger_c_convert, usb_charger_c_raw); | ||
1107 | } | ||
1108 | |||
1109 | static int ab8500_gpadc_usb_charger_c_open(struct inode *inode, | ||
1110 | struct file *file) | ||
1111 | { | ||
1112 | return single_open(file, ab8500_gpadc_usb_charger_c_print, | ||
1113 | inode->i_private); | ||
1114 | } | ||
1115 | |||
1116 | static const struct file_operations ab8500_gpadc_usb_charger_c_fops = { | ||
1117 | .open = ab8500_gpadc_usb_charger_c_open, | ||
1118 | .read = seq_read, | ||
1119 | .llseek = seq_lseek, | ||
1120 | .release = single_release, | ||
1121 | .owner = THIS_MODULE, | ||
1122 | }; | ||
1123 | |||
1124 | static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p) | ||
1125 | { | ||
1126 | int bk_bat_v_raw; | ||
1127 | int bk_bat_v_convert; | ||
1128 | struct ab8500_gpadc *gpadc; | ||
1129 | |||
1130 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
1131 | bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V); | ||
1132 | bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, | ||
1133 | BK_BAT_V, bk_bat_v_raw); | ||
1134 | |||
1135 | return seq_printf(s, "%d,0x%X\n", | ||
1136 | bk_bat_v_convert, bk_bat_v_raw); | ||
1137 | } | ||
1138 | |||
1139 | static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file) | ||
1140 | { | ||
1141 | return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private); | ||
1142 | } | ||
1143 | |||
1144 | static const struct file_operations ab8500_gpadc_bk_bat_v_fops = { | ||
1145 | .open = ab8500_gpadc_bk_bat_v_open, | ||
1146 | .read = seq_read, | ||
1147 | .llseek = seq_lseek, | ||
1148 | .release = single_release, | ||
1149 | .owner = THIS_MODULE, | ||
1150 | }; | ||
1151 | |||
1152 | static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p) | ||
1153 | { | ||
1154 | int die_temp_raw; | ||
1155 | int die_temp_convert; | ||
1156 | struct ab8500_gpadc *gpadc; | ||
1157 | |||
1158 | gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
1159 | die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP); | ||
1160 | die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, | ||
1161 | die_temp_raw); | ||
1162 | |||
1163 | return seq_printf(s, "%d,0x%X\n", | ||
1164 | die_temp_convert, die_temp_raw); | ||
1165 | } | ||
1166 | |||
1167 | static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file) | ||
1168 | { | ||
1169 | return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private); | ||
1170 | } | ||
1171 | |||
1172 | static const struct file_operations ab8500_gpadc_die_temp_fops = { | ||
1173 | .open = ab8500_gpadc_die_temp_open, | ||
1174 | .read = seq_read, | ||
1175 | .llseek = seq_lseek, | ||
1176 | .release = single_release, | ||
1177 | .owner = THIS_MODULE, | ||
1178 | }; | ||
1179 | |||
1180 | /* | ||
1181 | * return length of an ASCII numerical value, 0 is string is not a | ||
1182 | * numerical value. | ||
1183 | * string shall start at value 1st char. | ||
1184 | * string can be tailed with \0 or space or newline chars only. | ||
1185 | * value can be decimal or hexadecimal (prefixed 0x or 0X). | ||
1186 | */ | ||
1187 | static int strval_len(char *b) | ||
1188 | { | ||
1189 | char *s = b; | ||
1190 | if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) { | ||
1191 | s += 2; | ||
1192 | for (; *s && (*s != ' ') && (*s != '\n'); s++) { | ||
1193 | if (!isxdigit(*s)) | ||
1194 | return 0; | ||
1195 | } | ||
1196 | } else { | ||
1197 | if (*s == '-') | ||
1198 | s++; | ||
1199 | for (; *s && (*s != ' ') && (*s != '\n'); s++) { | ||
1200 | if (!isdigit(*s)) | ||
1201 | return 0; | ||
1202 | } | ||
1203 | } | ||
1204 | return (int) (s-b); | ||
1205 | } | ||
1206 | |||
1207 | /* | ||
1208 | * parse hwreg input data. | ||
1209 | * update global hwreg_cfg only if input data syntax is ok. | ||
1210 | */ | ||
1211 | static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg, | ||
1212 | struct device *dev) | ||
1213 | { | ||
1214 | uint write, val = 0; | ||
1215 | u8 regvalue; | ||
1216 | int ret; | ||
1217 | struct hwreg_cfg loc = { | ||
1218 | .bank = 0, /* default: invalid phys addr */ | ||
1219 | .addr = 0, /* default: invalid phys addr */ | ||
1220 | .fmt = 0, /* default: 32bit access, hex output */ | ||
1221 | .mask = 0xFFFFFFFF, /* default: no mask */ | ||
1222 | .shift = 0, /* default: no bit shift */ | ||
1223 | }; | ||
1224 | |||
1225 | /* read or write ? */ | ||
1226 | if (!strncmp(b, "read ", 5)) { | ||
1227 | write = 0; | ||
1228 | b += 5; | ||
1229 | } else if (!strncmp(b, "write ", 6)) { | ||
1230 | write = 1; | ||
1231 | b += 6; | ||
1232 | } else | ||
1233 | return -EINVAL; | ||
1234 | |||
1235 | /* OPTIONS -l|-w|-b -s -m -o */ | ||
1236 | while ((*b == ' ') || (*b == '-')) { | ||
1237 | if (*(b-1) != ' ') { | ||
1238 | b++; | ||
1239 | continue; | ||
1240 | } | ||
1241 | if ((!strncmp(b, "-d ", 3)) || | ||
1242 | (!strncmp(b, "-dec ", 5))) { | ||
1243 | b += (*(b+2) == ' ') ? 3 : 5; | ||
1244 | loc.fmt |= (1<<0); | ||
1245 | } else if ((!strncmp(b, "-h ", 3)) || | ||
1246 | (!strncmp(b, "-hex ", 5))) { | ||
1247 | b += (*(b+2) == ' ') ? 3 : 5; | ||
1248 | loc.fmt &= ~(1<<0); | ||
1249 | } else if ((!strncmp(b, "-m ", 3)) || | ||
1250 | (!strncmp(b, "-mask ", 6))) { | ||
1251 | b += (*(b+2) == ' ') ? 3 : 6; | ||
1252 | if (strval_len(b) == 0) | ||
1253 | return -EINVAL; | ||
1254 | loc.mask = simple_strtoul(b, &b, 0); | ||
1255 | } else if ((!strncmp(b, "-s ", 3)) || | ||
1256 | (!strncmp(b, "-shift ", 7))) { | ||
1257 | b += (*(b+2) == ' ') ? 3 : 7; | ||
1258 | if (strval_len(b) == 0) | ||
1259 | return -EINVAL; | ||
1260 | loc.shift = simple_strtol(b, &b, 0); | ||
1261 | } else { | ||
1262 | return -EINVAL; | ||
1263 | } | ||
1264 | } | ||
1265 | /* get arg BANK and ADDRESS */ | ||
1266 | if (strval_len(b) == 0) | ||
1267 | return -EINVAL; | ||
1268 | loc.bank = simple_strtoul(b, &b, 0); | ||
1269 | while (*b == ' ') | ||
1270 | b++; | ||
1271 | if (strval_len(b) == 0) | ||
1272 | return -EINVAL; | ||
1273 | loc.addr = simple_strtoul(b, &b, 0); | ||
1274 | |||
1275 | if (write) { | ||
1276 | while (*b == ' ') | ||
1277 | b++; | ||
1278 | if (strval_len(b) == 0) | ||
1279 | return -EINVAL; | ||
1280 | val = simple_strtoul(b, &b, 0); | ||
1281 | } | ||
1282 | |||
1283 | /* args are ok, update target cfg (mainly for read) */ | ||
1284 | *cfg = loc; | ||
1285 | |||
1286 | #ifdef ABB_HWREG_DEBUG | ||
1287 | pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d" | ||
1288 | "value=0x%X\n", (write) ? "write" : "read", | ||
1289 | REG_FMT_DEC(cfg) ? "decimal" : "hexa", | ||
1290 | cfg->addr, cfg->mask, cfg->shift, val); | ||
1291 | #endif | ||
1292 | |||
1293 | if (!write) | ||
1294 | return 0; | ||
1295 | |||
1296 | ret = abx500_get_register_interruptible(dev, | ||
1297 | (u8)cfg->bank, (u8)cfg->addr, ®value); | ||
1298 | if (ret < 0) { | ||
1299 | dev_err(dev, "abx500_get_reg fail %d, %d\n", | ||
1300 | ret, __LINE__); | ||
1301 | return -EINVAL; | ||
1302 | } | ||
1303 | |||
1304 | if (cfg->shift >= 0) { | ||
1305 | regvalue &= ~(cfg->mask << (cfg->shift)); | ||
1306 | val = (val & cfg->mask) << (cfg->shift); | ||
1307 | } else { | ||
1308 | regvalue &= ~(cfg->mask >> (-cfg->shift)); | ||
1309 | val = (val & cfg->mask) >> (-cfg->shift); | ||
1310 | } | ||
1311 | val = val | regvalue; | ||
1312 | |||
1313 | ret = abx500_set_register_interruptible(dev, | ||
1314 | (u8)cfg->bank, (u8)cfg->addr, (u8)val); | ||
1315 | if (ret < 0) { | ||
1316 | pr_err("abx500_set_reg failed %d, %d", ret, __LINE__); | ||
1317 | return -EINVAL; | ||
1318 | } | ||
1319 | |||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | static ssize_t ab8500_hwreg_write(struct file *file, | ||
1324 | const char __user *user_buf, size_t count, loff_t *ppos) | ||
1325 | { | ||
1326 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
1327 | char buf[128]; | ||
1328 | int buf_size, ret; | ||
1329 | |||
1330 | /* Get userspace string and assure termination */ | ||
1331 | buf_size = min(count, (sizeof(buf)-1)); | ||
1332 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1333 | return -EFAULT; | ||
1334 | buf[buf_size] = 0; | ||
1335 | |||
1336 | /* get args and process */ | ||
1337 | ret = hwreg_common_write(buf, &hwreg_cfg, dev); | ||
1338 | return (ret) ? ret : buf_size; | ||
1339 | } | ||
1340 | |||
1341 | /* | ||
1342 | * - irq subscribe/unsubscribe stuff | ||
1343 | */ | ||
1344 | static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p) | ||
1345 | { | ||
1346 | seq_printf(s, "%d\n", irq_first); | ||
1347 | |||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | static int ab8500_subscribe_unsubscribe_open(struct inode *inode, | ||
1352 | struct file *file) | ||
1353 | { | ||
1354 | return single_open(file, ab8500_subscribe_unsubscribe_print, | ||
1355 | inode->i_private); | ||
1356 | } | ||
1357 | |||
1358 | /* | ||
1359 | * Userspace should use poll() on this file. When an event occur | ||
1360 | * the blocking poll will be released. | ||
1361 | */ | ||
1362 | static ssize_t show_irq(struct device *dev, | ||
1363 | struct device_attribute *attr, char *buf) | ||
1364 | { | ||
1365 | unsigned long name; | ||
1366 | unsigned int irq_index; | ||
1367 | int err; | ||
1368 | |||
1369 | err = strict_strtoul(attr->attr.name, 0, &name); | ||
1370 | if (err) | ||
1371 | return err; | ||
1372 | |||
1373 | irq_index = name - irq_first; | ||
1374 | if (irq_index >= num_irqs) | ||
1375 | return -EINVAL; | ||
1376 | else | ||
1377 | return sprintf(buf, "%u\n", irq_count[irq_index]); | ||
1378 | } | ||
1379 | |||
1380 | static ssize_t ab8500_subscribe_write(struct file *file, | ||
1381 | const char __user *user_buf, | ||
1382 | size_t count, loff_t *ppos) | ||
1383 | { | ||
1384 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
1385 | char buf[32]; | ||
1386 | int buf_size; | ||
1387 | unsigned long user_val; | ||
1388 | int err; | ||
1389 | unsigned int irq_index; | ||
1390 | |||
1391 | /* Get userspace string and assure termination */ | ||
1392 | buf_size = min(count, (sizeof(buf)-1)); | ||
1393 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1394 | return -EFAULT; | ||
1395 | buf[buf_size] = 0; | ||
1396 | |||
1397 | err = strict_strtoul(buf, 0, &user_val); | ||
1398 | if (err) | ||
1399 | return -EINVAL; | ||
1400 | if (user_val < irq_first) { | ||
1401 | dev_err(dev, "debugfs error input < %d\n", irq_first); | ||
1402 | return -EINVAL; | ||
1403 | } | ||
1404 | if (user_val > irq_last) { | ||
1405 | dev_err(dev, "debugfs error input > %d\n", irq_last); | ||
1406 | return -EINVAL; | ||
1407 | } | ||
1408 | |||
1409 | irq_index = user_val - irq_first; | ||
1410 | if (irq_index >= num_irqs) | ||
1411 | return -EINVAL; | ||
1412 | |||
1413 | /* | ||
1414 | * This will create a sysfs file named <irq-nr> which userspace can | ||
1415 | * use to select or poll and get the AB8500 events | ||
1416 | */ | ||
1417 | dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute), | ||
1418 | GFP_KERNEL); | ||
1419 | event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL); | ||
1420 | sprintf(event_name[irq_index], "%lu", user_val); | ||
1421 | dev_attr[irq_index]->show = show_irq; | ||
1422 | dev_attr[irq_index]->store = NULL; | ||
1423 | dev_attr[irq_index]->attr.name = event_name[irq_index]; | ||
1424 | dev_attr[irq_index]->attr.mode = S_IRUGO; | ||
1425 | err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr); | ||
1426 | if (err < 0) { | ||
1427 | printk(KERN_ERR "sysfs_create_file failed %d\n", err); | ||
1428 | return err; | ||
1429 | } | ||
1430 | |||
1431 | err = request_threaded_irq(user_val, NULL, ab8500_debug_handler, | ||
1432 | IRQF_SHARED | IRQF_NO_SUSPEND, | ||
1433 | "ab8500-debug", &dev->kobj); | ||
1434 | if (err < 0) { | ||
1435 | printk(KERN_ERR "request_threaded_irq failed %d, %lu\n", | ||
1436 | err, user_val); | ||
1437 | sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr); | ||
1438 | return err; | ||
1439 | } | ||
1440 | |||
1441 | return buf_size; | ||
1442 | } | ||
1443 | |||
1444 | static ssize_t ab8500_unsubscribe_write(struct file *file, | ||
1445 | const char __user *user_buf, | ||
1446 | size_t count, loff_t *ppos) | ||
1447 | { | ||
1448 | struct device *dev = ((struct seq_file *)(file->private_data))->private; | ||
1449 | char buf[32]; | ||
1450 | int buf_size; | ||
1451 | unsigned long user_val; | ||
1452 | int err; | ||
1453 | unsigned int irq_index; | ||
1454 | |||
1455 | /* Get userspace string and assure termination */ | ||
1456 | buf_size = min(count, (sizeof(buf)-1)); | ||
1457 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1458 | return -EFAULT; | ||
1459 | buf[buf_size] = 0; | ||
1460 | |||
1461 | err = strict_strtoul(buf, 0, &user_val); | ||
1462 | if (err) | ||
1463 | return -EINVAL; | ||
1464 | if (user_val < irq_first) { | ||
1465 | dev_err(dev, "debugfs error input < %d\n", irq_first); | ||
1466 | return -EINVAL; | ||
1467 | } | ||
1468 | if (user_val > irq_last) { | ||
1469 | dev_err(dev, "debugfs error input > %d\n", irq_last); | ||
1470 | return -EINVAL; | ||
1471 | } | ||
1472 | |||
1473 | irq_index = user_val - irq_first; | ||
1474 | if (irq_index >= num_irqs) | ||
1475 | return -EINVAL; | ||
1476 | |||
1477 | /* Set irq count to 0 when unsubscribe */ | ||
1478 | irq_count[irq_index] = 0; | ||
1479 | |||
1480 | if (dev_attr[irq_index]) | ||
1481 | sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr); | ||
1482 | |||
1483 | |||
1484 | free_irq(user_val, &dev->kobj); | ||
1485 | kfree(event_name[irq_index]); | ||
1486 | kfree(dev_attr[irq_index]); | ||
1487 | |||
1488 | return buf_size; | ||
1489 | } | ||
1490 | |||
1491 | /* | ||
1492 | * - several deubgfs nodes fops | ||
1493 | */ | ||
1494 | |||
522 | static const struct file_operations ab8500_bank_fops = { | 1495 | static const struct file_operations ab8500_bank_fops = { |
523 | .open = ab8500_bank_open, | 1496 | .open = ab8500_bank_open, |
524 | .write = ab8500_bank_write, | 1497 | .write = ab8500_bank_write, |
@@ -546,64 +1519,231 @@ static const struct file_operations ab8500_val_fops = { | |||
546 | .owner = THIS_MODULE, | 1519 | .owner = THIS_MODULE, |
547 | }; | 1520 | }; |
548 | 1521 | ||
1522 | static const struct file_operations ab8500_interrupts_fops = { | ||
1523 | .open = ab8500_interrupts_open, | ||
1524 | .read = seq_read, | ||
1525 | .llseek = seq_lseek, | ||
1526 | .release = single_release, | ||
1527 | .owner = THIS_MODULE, | ||
1528 | }; | ||
1529 | |||
1530 | static const struct file_operations ab8500_subscribe_fops = { | ||
1531 | .open = ab8500_subscribe_unsubscribe_open, | ||
1532 | .write = ab8500_subscribe_write, | ||
1533 | .read = seq_read, | ||
1534 | .llseek = seq_lseek, | ||
1535 | .release = single_release, | ||
1536 | .owner = THIS_MODULE, | ||
1537 | }; | ||
1538 | |||
1539 | static const struct file_operations ab8500_unsubscribe_fops = { | ||
1540 | .open = ab8500_subscribe_unsubscribe_open, | ||
1541 | .write = ab8500_unsubscribe_write, | ||
1542 | .read = seq_read, | ||
1543 | .llseek = seq_lseek, | ||
1544 | .release = single_release, | ||
1545 | .owner = THIS_MODULE, | ||
1546 | }; | ||
1547 | |||
1548 | static const struct file_operations ab8500_hwreg_fops = { | ||
1549 | .open = ab8500_hwreg_open, | ||
1550 | .write = ab8500_hwreg_write, | ||
1551 | .read = seq_read, | ||
1552 | .llseek = seq_lseek, | ||
1553 | .release = single_release, | ||
1554 | .owner = THIS_MODULE, | ||
1555 | }; | ||
1556 | |||
549 | static struct dentry *ab8500_dir; | 1557 | static struct dentry *ab8500_dir; |
550 | static struct dentry *ab8500_reg_file; | 1558 | static struct dentry *ab8500_gpadc_dir; |
551 | static struct dentry *ab8500_bank_file; | ||
552 | static struct dentry *ab8500_address_file; | ||
553 | static struct dentry *ab8500_val_file; | ||
554 | 1559 | ||
555 | static int ab8500_debug_probe(struct platform_device *plf) | 1560 | static int ab8500_debug_probe(struct platform_device *plf) |
556 | { | 1561 | { |
1562 | struct dentry *file; | ||
1563 | int ret = -ENOMEM; | ||
1564 | struct ab8500 *ab8500; | ||
557 | debug_bank = AB8500_MISC; | 1565 | debug_bank = AB8500_MISC; |
558 | debug_address = AB8500_REV_REG & 0x00FF; | 1566 | debug_address = AB8500_REV_REG & 0x00FF; |
559 | 1567 | ||
1568 | ab8500 = dev_get_drvdata(plf->dev.parent); | ||
1569 | num_irqs = ab8500->mask_size; | ||
1570 | |||
1571 | irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL); | ||
1572 | if (!irq_count) | ||
1573 | return -ENOMEM; | ||
1574 | |||
1575 | dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL); | ||
1576 | if (!dev_attr) | ||
1577 | goto out_freeirq_count; | ||
1578 | |||
1579 | event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL); | ||
1580 | if (!event_name) | ||
1581 | goto out_freedev_attr; | ||
1582 | |||
1583 | irq_first = platform_get_irq_byname(plf, "IRQ_FIRST"); | ||
1584 | if (irq_first < 0) { | ||
1585 | dev_err(&plf->dev, "First irq not found, err %d\n", | ||
1586 | irq_first); | ||
1587 | ret = irq_first; | ||
1588 | goto out_freeevent_name; | ||
1589 | } | ||
1590 | |||
1591 | irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); | ||
1592 | if (irq_last < 0) { | ||
1593 | dev_err(&plf->dev, "Last irq not found, err %d\n", | ||
1594 | irq_last); | ||
1595 | ret = irq_last; | ||
1596 | goto out_freeevent_name; | ||
1597 | } | ||
1598 | |||
560 | ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); | 1599 | ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); |
561 | if (!ab8500_dir) | 1600 | if (!ab8500_dir) |
562 | goto exit_no_debugfs; | 1601 | goto err; |
1602 | |||
1603 | ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING, | ||
1604 | ab8500_dir); | ||
1605 | if (!ab8500_gpadc_dir) | ||
1606 | goto err; | ||
1607 | |||
1608 | file = debugfs_create_file("all-bank-registers", S_IRUGO, | ||
1609 | ab8500_dir, &plf->dev, &ab8500_registers_fops); | ||
1610 | if (!file) | ||
1611 | goto err; | ||
1612 | |||
1613 | file = debugfs_create_file("all-banks", S_IRUGO, | ||
1614 | ab8500_dir, &plf->dev, &ab8500_all_banks_fops); | ||
1615 | if (!file) | ||
1616 | goto err; | ||
1617 | |||
1618 | file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR), | ||
1619 | ab8500_dir, &plf->dev, &ab8500_bank_fops); | ||
1620 | if (!file) | ||
1621 | goto err; | ||
1622 | |||
1623 | file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR), | ||
1624 | ab8500_dir, &plf->dev, &ab8500_address_fops); | ||
1625 | if (!file) | ||
1626 | goto err; | ||
1627 | |||
1628 | file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR), | ||
1629 | ab8500_dir, &plf->dev, &ab8500_val_fops); | ||
1630 | if (!file) | ||
1631 | goto err; | ||
563 | 1632 | ||
564 | ab8500_reg_file = debugfs_create_file("all-bank-registers", | 1633 | file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR), |
565 | S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops); | 1634 | ab8500_dir, &plf->dev, &ab8500_subscribe_fops); |
566 | if (!ab8500_reg_file) | 1635 | if (!file) |
567 | goto exit_destroy_dir; | 1636 | goto err; |
568 | 1637 | ||
569 | ab8500_bank_file = debugfs_create_file("register-bank", | 1638 | if (is_ab8500(ab8500)) |
570 | (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops); | 1639 | num_interrupt_lines = AB8500_NR_IRQS; |
571 | if (!ab8500_bank_file) | 1640 | else if (is_ab8505(ab8500)) |
572 | goto exit_destroy_reg; | 1641 | num_interrupt_lines = AB8505_NR_IRQS; |
1642 | else if (is_ab9540(ab8500)) | ||
1643 | num_interrupt_lines = AB9540_NR_IRQS; | ||
573 | 1644 | ||
574 | ab8500_address_file = debugfs_create_file("register-address", | 1645 | file = debugfs_create_file("interrupts", (S_IRUGO), |
575 | (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, | 1646 | ab8500_dir, &plf->dev, &ab8500_interrupts_fops); |
576 | &ab8500_address_fops); | 1647 | if (!file) |
577 | if (!ab8500_address_file) | 1648 | goto err; |
578 | goto exit_destroy_bank; | ||
579 | 1649 | ||
580 | ab8500_val_file = debugfs_create_file("register-value", | 1650 | file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR), |
581 | (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops); | 1651 | ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops); |
582 | if (!ab8500_val_file) | 1652 | if (!file) |
583 | goto exit_destroy_address; | 1653 | goto err; |
1654 | |||
1655 | file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR), | ||
1656 | ab8500_dir, &plf->dev, &ab8500_hwreg_fops); | ||
1657 | if (!file) | ||
1658 | goto err; | ||
1659 | |||
1660 | file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR), | ||
1661 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops); | ||
1662 | if (!file) | ||
1663 | goto err; | ||
1664 | |||
1665 | file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR), | ||
1666 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops); | ||
1667 | if (!file) | ||
1668 | goto err; | ||
1669 | |||
1670 | file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR), | ||
1671 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops); | ||
1672 | if (!file) | ||
1673 | goto err; | ||
1674 | |||
1675 | file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR), | ||
1676 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops); | ||
1677 | if (!file) | ||
1678 | goto err; | ||
1679 | |||
1680 | file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR), | ||
1681 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops); | ||
1682 | if (!file) | ||
1683 | goto err; | ||
1684 | |||
1685 | file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR), | ||
1686 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops); | ||
1687 | if (!file) | ||
1688 | goto err; | ||
1689 | |||
1690 | file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR), | ||
1691 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops); | ||
1692 | if (!file) | ||
1693 | goto err; | ||
1694 | |||
1695 | file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR), | ||
1696 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops); | ||
1697 | if (!file) | ||
1698 | goto err; | ||
1699 | |||
1700 | file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR), | ||
1701 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops); | ||
1702 | if (!file) | ||
1703 | goto err; | ||
1704 | |||
1705 | file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR), | ||
1706 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops); | ||
1707 | if (!file) | ||
1708 | goto err; | ||
1709 | |||
1710 | file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR), | ||
1711 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops); | ||
1712 | if (!file) | ||
1713 | goto err; | ||
1714 | |||
1715 | file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR), | ||
1716 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops); | ||
1717 | if (!file) | ||
1718 | goto err; | ||
1719 | |||
1720 | file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR), | ||
1721 | ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops); | ||
1722 | if (!file) | ||
1723 | goto err; | ||
584 | 1724 | ||
585 | return 0; | 1725 | return 0; |
586 | 1726 | ||
587 | exit_destroy_address: | 1727 | err: |
588 | debugfs_remove(ab8500_address_file); | 1728 | if (ab8500_dir) |
589 | exit_destroy_bank: | 1729 | debugfs_remove_recursive(ab8500_dir); |
590 | debugfs_remove(ab8500_bank_file); | ||
591 | exit_destroy_reg: | ||
592 | debugfs_remove(ab8500_reg_file); | ||
593 | exit_destroy_dir: | ||
594 | debugfs_remove(ab8500_dir); | ||
595 | exit_no_debugfs: | ||
596 | dev_err(&plf->dev, "failed to create debugfs entries.\n"); | 1730 | dev_err(&plf->dev, "failed to create debugfs entries.\n"); |
597 | return -ENOMEM; | 1731 | out_freeevent_name: |
1732 | kfree(event_name); | ||
1733 | out_freedev_attr: | ||
1734 | kfree(dev_attr); | ||
1735 | out_freeirq_count: | ||
1736 | kfree(irq_count); | ||
1737 | |||
1738 | return ret; | ||
598 | } | 1739 | } |
599 | 1740 | ||
600 | static int ab8500_debug_remove(struct platform_device *plf) | 1741 | static int ab8500_debug_remove(struct platform_device *plf) |
601 | { | 1742 | { |
602 | debugfs_remove(ab8500_val_file); | 1743 | debugfs_remove_recursive(ab8500_dir); |
603 | debugfs_remove(ab8500_address_file); | 1744 | kfree(event_name); |
604 | debugfs_remove(ab8500_bank_file); | 1745 | kfree(dev_attr); |
605 | debugfs_remove(ab8500_reg_file); | 1746 | kfree(irq_count); |
606 | debugfs_remove(ab8500_dir); | ||
607 | 1747 | ||
608 | return 0; | 1748 | return 0; |
609 | } | 1749 | } |
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 3fb1f40d6389..b1f3561b023f 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/pm_runtime.h> | ||
15 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
16 | #include <linux/completion.h> | 17 | #include <linux/completion.h> |
17 | #include <linux/regulator/consumer.h> | 18 | #include <linux/regulator/consumer.h> |
@@ -82,6 +83,11 @@ | |||
82 | /* This is used to not lose precision when dividing to get gain and offset */ | 83 | /* This is used to not lose precision when dividing to get gain and offset */ |
83 | #define CALIB_SCALE 1000 | 84 | #define CALIB_SCALE 1000 |
84 | 85 | ||
86 | /* Time in ms before disabling regulator */ | ||
87 | #define GPADC_AUDOSUSPEND_DELAY 1 | ||
88 | |||
89 | #define CONVERSION_TIME 500 /* ms */ | ||
90 | |||
85 | enum cal_channels { | 91 | enum cal_channels { |
86 | ADC_INPUT_VMAIN = 0, | 92 | ADC_INPUT_VMAIN = 0, |
87 | ADC_INPUT_BTEMP, | 93 | ADC_INPUT_BTEMP, |
@@ -102,10 +108,10 @@ struct adc_cal_data { | |||
102 | 108 | ||
103 | /** | 109 | /** |
104 | * struct ab8500_gpadc - AB8500 GPADC device information | 110 | * struct ab8500_gpadc - AB8500 GPADC device information |
105 | * @chip_id ABB chip id | ||
106 | * @dev: pointer to the struct device | 111 | * @dev: pointer to the struct device |
107 | * @node: a list of AB8500 GPADCs, hence prepared for | 112 | * @node: a list of AB8500 GPADCs, hence prepared for |
108 | reentrance | 113 | reentrance |
114 | * @parent: pointer to the struct ab8500 | ||
109 | * @ab8500_gpadc_complete: pointer to the struct completion, to indicate | 115 | * @ab8500_gpadc_complete: pointer to the struct completion, to indicate |
110 | * the completion of gpadc conversion | 116 | * the completion of gpadc conversion |
111 | * @ab8500_gpadc_lock: structure of type mutex | 117 | * @ab8500_gpadc_lock: structure of type mutex |
@@ -114,9 +120,9 @@ struct adc_cal_data { | |||
114 | * @cal_data array of ADC calibration data structs | 120 | * @cal_data array of ADC calibration data structs |
115 | */ | 121 | */ |
116 | struct ab8500_gpadc { | 122 | struct ab8500_gpadc { |
117 | u8 chip_id; | ||
118 | struct device *dev; | 123 | struct device *dev; |
119 | struct list_head node; | 124 | struct list_head node; |
125 | struct ab8500 *parent; | ||
120 | struct completion ab8500_gpadc_complete; | 126 | struct completion ab8500_gpadc_complete; |
121 | struct mutex ab8500_gpadc_lock; | 127 | struct mutex ab8500_gpadc_lock; |
122 | struct regulator *regu; | 128 | struct regulator *regu; |
@@ -282,8 +288,9 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
282 | return -ENODEV; | 288 | return -ENODEV; |
283 | 289 | ||
284 | mutex_lock(&gpadc->ab8500_gpadc_lock); | 290 | mutex_lock(&gpadc->ab8500_gpadc_lock); |
291 | |||
285 | /* Enable VTVout LDO this is required for GPADC */ | 292 | /* Enable VTVout LDO this is required for GPADC */ |
286 | regulator_enable(gpadc->regu); | 293 | pm_runtime_get_sync(gpadc->dev); |
287 | 294 | ||
288 | /* Check if ADC is not busy, lock and proceed */ | 295 | /* Check if ADC is not busy, lock and proceed */ |
289 | do { | 296 | do { |
@@ -332,7 +339,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
332 | EN_BUF | EN_ICHAR); | 339 | EN_BUF | EN_ICHAR); |
333 | break; | 340 | break; |
334 | case BTEMP_BALL: | 341 | case BTEMP_BALL: |
335 | if (gpadc->chip_id >= AB8500_CUT3P0) { | 342 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { |
336 | /* Turn on btemp pull-up on ABB 3.0 */ | 343 | /* Turn on btemp pull-up on ABB 3.0 */ |
337 | ret = abx500_mask_and_set_register_interruptible( | 344 | ret = abx500_mask_and_set_register_interruptible( |
338 | gpadc->dev, | 345 | gpadc->dev, |
@@ -344,7 +351,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
344 | * Delay might be needed for ABB8500 cut 3.0, if not, remove | 351 | * Delay might be needed for ABB8500 cut 3.0, if not, remove |
345 | * when hardware will be available | 352 | * when hardware will be available |
346 | */ | 353 | */ |
347 | msleep(1); | 354 | usleep_range(1000, 1000); |
348 | break; | 355 | break; |
349 | } | 356 | } |
350 | /* Intentional fallthrough */ | 357 | /* Intentional fallthrough */ |
@@ -367,7 +374,8 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
367 | goto out; | 374 | goto out; |
368 | } | 375 | } |
369 | /* wait for completion of conversion */ | 376 | /* wait for completion of conversion */ |
370 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, 2*HZ)) { | 377 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, |
378 | msecs_to_jiffies(CONVERSION_TIME))) { | ||
371 | dev_err(gpadc->dev, | 379 | dev_err(gpadc->dev, |
372 | "timeout: didn't receive GPADC conversion interrupt\n"); | 380 | "timeout: didn't receive GPADC conversion interrupt\n"); |
373 | ret = -EINVAL; | 381 | ret = -EINVAL; |
@@ -397,8 +405,10 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
397 | dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); | 405 | dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); |
398 | goto out; | 406 | goto out; |
399 | } | 407 | } |
400 | /* Disable VTVout LDO this is required for GPADC */ | 408 | |
401 | regulator_disable(gpadc->regu); | 409 | pm_runtime_mark_last_busy(gpadc->dev); |
410 | pm_runtime_put_autosuspend(gpadc->dev); | ||
411 | |||
402 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 412 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
403 | 413 | ||
404 | return (high_data << 8) | low_data; | 414 | return (high_data << 8) | low_data; |
@@ -412,7 +422,9 @@ out: | |||
412 | */ | 422 | */ |
413 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 423 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
414 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | 424 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); |
415 | regulator_disable(gpadc->regu); | 425 | |
426 | pm_runtime_put(gpadc->dev); | ||
427 | |||
416 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 428 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
417 | dev_err(gpadc->dev, | 429 | dev_err(gpadc->dev, |
418 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); | 430 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); |
@@ -571,6 +583,28 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
571 | gpadc->cal_data[ADC_INPUT_VBAT].offset); | 583 | gpadc->cal_data[ADC_INPUT_VBAT].offset); |
572 | } | 584 | } |
573 | 585 | ||
586 | static int ab8500_gpadc_runtime_suspend(struct device *dev) | ||
587 | { | ||
588 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | ||
589 | |||
590 | regulator_disable(gpadc->regu); | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static int ab8500_gpadc_runtime_resume(struct device *dev) | ||
595 | { | ||
596 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | ||
597 | |||
598 | regulator_enable(gpadc->regu); | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static int ab8500_gpadc_runtime_idle(struct device *dev) | ||
603 | { | ||
604 | pm_runtime_suspend(dev); | ||
605 | return 0; | ||
606 | } | ||
607 | |||
574 | static int ab8500_gpadc_probe(struct platform_device *pdev) | 608 | static int ab8500_gpadc_probe(struct platform_device *pdev) |
575 | { | 609 | { |
576 | int ret = 0; | 610 | int ret = 0; |
@@ -591,6 +625,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
591 | } | 625 | } |
592 | 626 | ||
593 | gpadc->dev = &pdev->dev; | 627 | gpadc->dev = &pdev->dev; |
628 | gpadc->parent = dev_get_drvdata(pdev->dev.parent); | ||
594 | mutex_init(&gpadc->ab8500_gpadc_lock); | 629 | mutex_init(&gpadc->ab8500_gpadc_lock); |
595 | 630 | ||
596 | /* Initialize completion used to notify completion of conversion */ | 631 | /* Initialize completion used to notify completion of conversion */ |
@@ -607,14 +642,6 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
607 | goto fail; | 642 | goto fail; |
608 | } | 643 | } |
609 | 644 | ||
610 | /* Get Chip ID of the ABB ASIC */ | ||
611 | ret = abx500_get_chip_id(gpadc->dev); | ||
612 | if (ret < 0) { | ||
613 | dev_err(gpadc->dev, "failed to get chip ID\n"); | ||
614 | goto fail_irq; | ||
615 | } | ||
616 | gpadc->chip_id = (u8) ret; | ||
617 | |||
618 | /* VTVout LDO used to power up ab8500-GPADC */ | 645 | /* VTVout LDO used to power up ab8500-GPADC */ |
619 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); | 646 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); |
620 | if (IS_ERR(gpadc->regu)) { | 647 | if (IS_ERR(gpadc->regu)) { |
@@ -622,6 +649,16 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
622 | dev_err(gpadc->dev, "failed to get vtvout LDO\n"); | 649 | dev_err(gpadc->dev, "failed to get vtvout LDO\n"); |
623 | goto fail_irq; | 650 | goto fail_irq; |
624 | } | 651 | } |
652 | |||
653 | platform_set_drvdata(pdev, gpadc); | ||
654 | |||
655 | regulator_enable(gpadc->regu); | ||
656 | |||
657 | pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY); | ||
658 | pm_runtime_use_autosuspend(gpadc->dev); | ||
659 | pm_runtime_set_active(gpadc->dev); | ||
660 | pm_runtime_enable(gpadc->dev); | ||
661 | |||
625 | ab8500_gpadc_read_calibration_data(gpadc); | 662 | ab8500_gpadc_read_calibration_data(gpadc); |
626 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); | 663 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); |
627 | dev_dbg(gpadc->dev, "probe success\n"); | 664 | dev_dbg(gpadc->dev, "probe success\n"); |
@@ -642,19 +679,34 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) | |||
642 | list_del(&gpadc->node); | 679 | list_del(&gpadc->node); |
643 | /* remove interrupt - completion of Sw ADC conversion */ | 680 | /* remove interrupt - completion of Sw ADC conversion */ |
644 | free_irq(gpadc->irq, gpadc); | 681 | free_irq(gpadc->irq, gpadc); |
645 | /* disable VTVout LDO that is being used by GPADC */ | 682 | |
646 | regulator_put(gpadc->regu); | 683 | pm_runtime_get_sync(gpadc->dev); |
684 | pm_runtime_disable(gpadc->dev); | ||
685 | |||
686 | regulator_disable(gpadc->regu); | ||
687 | |||
688 | pm_runtime_set_suspended(gpadc->dev); | ||
689 | |||
690 | pm_runtime_put_noidle(gpadc->dev); | ||
691 | |||
647 | kfree(gpadc); | 692 | kfree(gpadc); |
648 | gpadc = NULL; | 693 | gpadc = NULL; |
649 | return 0; | 694 | return 0; |
650 | } | 695 | } |
651 | 696 | ||
697 | static const struct dev_pm_ops ab8500_gpadc_pm_ops = { | ||
698 | SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, | ||
699 | ab8500_gpadc_runtime_resume, | ||
700 | ab8500_gpadc_runtime_idle) | ||
701 | }; | ||
702 | |||
652 | static struct platform_driver ab8500_gpadc_driver = { | 703 | static struct platform_driver ab8500_gpadc_driver = { |
653 | .probe = ab8500_gpadc_probe, | 704 | .probe = ab8500_gpadc_probe, |
654 | .remove = ab8500_gpadc_remove, | 705 | .remove = ab8500_gpadc_remove, |
655 | .driver = { | 706 | .driver = { |
656 | .name = "ab8500-gpadc", | 707 | .name = "ab8500-gpadc", |
657 | .owner = THIS_MODULE, | 708 | .owner = THIS_MODULE, |
709 | .pm = &ab8500_gpadc_pm_ops, | ||
658 | }, | 710 | }, |
659 | }; | 711 | }; |
660 | 712 | ||
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 8a33b2c7eead..108fd86552f0 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c | |||
@@ -7,12 +7,73 @@ | |||
7 | #include <linux/err.h> | 7 | #include <linux/err.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
10 | #include <linux/pm.h> | ||
11 | #include <linux/reboot.h> | ||
12 | #include <linux/signal.h> | ||
13 | #include <linux/power_supply.h> | ||
10 | #include <linux/mfd/abx500.h> | 14 | #include <linux/mfd/abx500.h> |
11 | #include <linux/mfd/abx500/ab8500.h> | 15 | #include <linux/mfd/abx500/ab8500.h> |
12 | #include <linux/mfd/abx500/ab8500-sysctrl.h> | 16 | #include <linux/mfd/abx500/ab8500-sysctrl.h> |
13 | 17 | ||
14 | static struct device *sysctrl_dev; | 18 | static struct device *sysctrl_dev; |
15 | 19 | ||
20 | void ab8500_power_off(void) | ||
21 | { | ||
22 | sigset_t old; | ||
23 | sigset_t all; | ||
24 | static char *pss[] = {"ab8500_ac", "ab8500_usb"}; | ||
25 | int i; | ||
26 | bool charger_present = false; | ||
27 | union power_supply_propval val; | ||
28 | struct power_supply *psy; | ||
29 | int ret; | ||
30 | |||
31 | /* | ||
32 | * If we have a charger connected and we're powering off, | ||
33 | * reboot into charge-only mode. | ||
34 | */ | ||
35 | |||
36 | for (i = 0; i < ARRAY_SIZE(pss); i++) { | ||
37 | psy = power_supply_get_by_name(pss[i]); | ||
38 | if (!psy) | ||
39 | continue; | ||
40 | |||
41 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); | ||
42 | |||
43 | if (!ret && val.intval) { | ||
44 | charger_present = true; | ||
45 | break; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | if (!charger_present) | ||
50 | goto shutdown; | ||
51 | |||
52 | /* Check if battery is known */ | ||
53 | psy = power_supply_get_by_name("ab8500_btemp"); | ||
54 | if (psy) { | ||
55 | ret = psy->get_property(psy, POWER_SUPPLY_PROP_TECHNOLOGY, | ||
56 | &val); | ||
57 | if (!ret && val.intval != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) { | ||
58 | printk(KERN_INFO | ||
59 | "Charger \"%s\" is connected with known battery." | ||
60 | " Rebooting.\n", | ||
61 | pss[i]); | ||
62 | machine_restart("charging"); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | shutdown: | ||
67 | sigfillset(&all); | ||
68 | |||
69 | if (!sigprocmask(SIG_BLOCK, &all, &old)) { | ||
70 | (void)ab8500_sysctrl_set(AB8500_STW4500CTRL1, | ||
71 | AB8500_STW4500CTRL1_SWOFF | | ||
72 | AB8500_STW4500CTRL1_SWRESET4500N); | ||
73 | (void)sigprocmask(SIG_SETMASK, &old, NULL); | ||
74 | } | ||
75 | } | ||
76 | |||
16 | static inline bool valid_bank(u8 bank) | 77 | static inline bool valid_bank(u8 bank) |
17 | { | 78 | { |
18 | return ((bank == AB8500_SYS_CTRL1_BLOCK) || | 79 | return ((bank == AB8500_SYS_CTRL1_BLOCK) || |
@@ -33,6 +94,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value) | |||
33 | return abx500_get_register_interruptible(sysctrl_dev, bank, | 94 | return abx500_get_register_interruptible(sysctrl_dev, bank, |
34 | (u8)(reg & 0xFF), value); | 95 | (u8)(reg & 0xFF), value); |
35 | } | 96 | } |
97 | EXPORT_SYMBOL(ab8500_sysctrl_read); | ||
36 | 98 | ||
37 | int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) | 99 | int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) |
38 | { | 100 | { |
@@ -48,10 +110,40 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) | |||
48 | return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank, | 110 | return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank, |
49 | (u8)(reg & 0xFF), mask, value); | 111 | (u8)(reg & 0xFF), mask, value); |
50 | } | 112 | } |
113 | EXPORT_SYMBOL(ab8500_sysctrl_write); | ||
51 | 114 | ||
52 | static int ab8500_sysctrl_probe(struct platform_device *pdev) | 115 | static int ab8500_sysctrl_probe(struct platform_device *pdev) |
53 | { | 116 | { |
117 | struct ab8500_platform_data *plat; | ||
118 | struct ab8500_sysctrl_platform_data *pdata; | ||
119 | |||
54 | sysctrl_dev = &pdev->dev; | 120 | sysctrl_dev = &pdev->dev; |
121 | plat = dev_get_platdata(pdev->dev.parent); | ||
122 | if (plat->pm_power_off) | ||
123 | pm_power_off = ab8500_power_off; | ||
124 | |||
125 | pdata = plat->sysctrl; | ||
126 | |||
127 | if (pdata) { | ||
128 | int ret, i, j; | ||
129 | |||
130 | for (i = AB8500_SYSCLKREQ1RFCLKBUF; | ||
131 | i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) { | ||
132 | j = i - AB8500_SYSCLKREQ1RFCLKBUF; | ||
133 | ret = ab8500_sysctrl_write(i, 0xff, | ||
134 | pdata->initial_req_buf_config[j]); | ||
135 | dev_dbg(&pdev->dev, | ||
136 | "Setting SysClkReq%dRfClkBuf 0x%X\n", | ||
137 | j + 1, | ||
138 | pdata->initial_req_buf_config[j]); | ||
139 | if (ret < 0) { | ||
140 | dev_err(&pdev->dev, | ||
141 | "unable to set sysClkReq%dRfClkBuf: " | ||
142 | "%d\n", j + 1, ret); | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | |||
55 | return 0; | 147 | return 0; |
56 | } | 148 | } |
57 | 149 | ||
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 7ce65f49480f..9818afba2515 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c | |||
@@ -153,6 +153,22 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq) | |||
153 | } | 153 | } |
154 | EXPORT_SYMBOL(abx500_startup_irq_enabled); | 154 | EXPORT_SYMBOL(abx500_startup_irq_enabled); |
155 | 155 | ||
156 | void abx500_dump_all_banks(void) | ||
157 | { | ||
158 | struct abx500_ops *ops; | ||
159 | struct device dummy_child = {0}; | ||
160 | struct abx500_device_entry *dev_entry; | ||
161 | |||
162 | list_for_each_entry(dev_entry, &abx500_list, list) { | ||
163 | dummy_child.parent = dev_entry->dev; | ||
164 | ops = &dev_entry->ops; | ||
165 | |||
166 | if ((ops != NULL) && (ops->dump_all_banks != NULL)) | ||
167 | ops->dump_all_banks(&dummy_child); | ||
168 | } | ||
169 | } | ||
170 | EXPORT_SYMBOL(abx500_dump_all_banks); | ||
171 | |||
156 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); | 172 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); |
157 | MODULE_DESCRIPTION("ABX500 core driver"); | 173 | MODULE_DESCRIPTION("ABX500 core driver"); |
158 | MODULE_LICENSE("GPL"); | 174 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 222c03a5ddc0..b562c7bf8a46 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c | |||
@@ -115,7 +115,7 @@ static irqreturn_t arizona_underclocked(int irq, void *data) | |||
115 | if (val & ARIZONA_ADC_UNDERCLOCKED_STS) | 115 | if (val & ARIZONA_ADC_UNDERCLOCKED_STS) |
116 | dev_err(arizona->dev, "ADC underclocked\n"); | 116 | dev_err(arizona->dev, "ADC underclocked\n"); |
117 | if (val & ARIZONA_MIXER_UNDERCLOCKED_STS) | 117 | if (val & ARIZONA_MIXER_UNDERCLOCKED_STS) |
118 | dev_err(arizona->dev, "Mixer underclocked\n"); | 118 | dev_err(arizona->dev, "Mixer dropped sample\n"); |
119 | 119 | ||
120 | return IRQ_HANDLED; | 120 | return IRQ_HANDLED; |
121 | } | 121 | } |
@@ -263,10 +263,36 @@ static int arizona_runtime_suspend(struct device *dev) | |||
263 | } | 263 | } |
264 | #endif | 264 | #endif |
265 | 265 | ||
266 | #ifdef CONFIG_PM_SLEEP | ||
267 | static int arizona_resume_noirq(struct device *dev) | ||
268 | { | ||
269 | struct arizona *arizona = dev_get_drvdata(dev); | ||
270 | |||
271 | dev_dbg(arizona->dev, "Early resume, disabling IRQ\n"); | ||
272 | disable_irq(arizona->irq); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int arizona_resume(struct device *dev) | ||
278 | { | ||
279 | struct arizona *arizona = dev_get_drvdata(dev); | ||
280 | |||
281 | dev_dbg(arizona->dev, "Late resume, reenabling IRQ\n"); | ||
282 | enable_irq(arizona->irq); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | #endif | ||
287 | |||
266 | const struct dev_pm_ops arizona_pm_ops = { | 288 | const struct dev_pm_ops arizona_pm_ops = { |
267 | SET_RUNTIME_PM_OPS(arizona_runtime_suspend, | 289 | SET_RUNTIME_PM_OPS(arizona_runtime_suspend, |
268 | arizona_runtime_resume, | 290 | arizona_runtime_resume, |
269 | NULL) | 291 | NULL) |
292 | SET_SYSTEM_SLEEP_PM_OPS(NULL, arizona_resume) | ||
293 | #ifdef CONFIG_PM_SLEEP | ||
294 | .resume_noirq = arizona_resume_noirq, | ||
295 | #endif | ||
270 | }; | 296 | }; |
271 | EXPORT_SYMBOL_GPL(arizona_pm_ops); | 297 | EXPORT_SYMBOL_GPL(arizona_pm_ops); |
272 | 298 | ||
@@ -275,19 +301,19 @@ static struct mfd_cell early_devs[] = { | |||
275 | }; | 301 | }; |
276 | 302 | ||
277 | static struct mfd_cell wm5102_devs[] = { | 303 | static struct mfd_cell wm5102_devs[] = { |
304 | { .name = "arizona-micsupp" }, | ||
278 | { .name = "arizona-extcon" }, | 305 | { .name = "arizona-extcon" }, |
279 | { .name = "arizona-gpio" }, | 306 | { .name = "arizona-gpio" }, |
280 | { .name = "arizona-haptics" }, | 307 | { .name = "arizona-haptics" }, |
281 | { .name = "arizona-micsupp" }, | ||
282 | { .name = "arizona-pwm" }, | 308 | { .name = "arizona-pwm" }, |
283 | { .name = "wm5102-codec" }, | 309 | { .name = "wm5102-codec" }, |
284 | }; | 310 | }; |
285 | 311 | ||
286 | static struct mfd_cell wm5110_devs[] = { | 312 | static struct mfd_cell wm5110_devs[] = { |
313 | { .name = "arizona-micsupp" }, | ||
287 | { .name = "arizona-extcon" }, | 314 | { .name = "arizona-extcon" }, |
288 | { .name = "arizona-gpio" }, | 315 | { .name = "arizona-gpio" }, |
289 | { .name = "arizona-haptics" }, | 316 | { .name = "arizona-haptics" }, |
290 | { .name = "arizona-micsupp" }, | ||
291 | { .name = "arizona-pwm" }, | 317 | { .name = "arizona-pwm" }, |
292 | { .name = "wm5110-codec" }, | 318 | { .name = "wm5110-codec" }, |
293 | }; | 319 | }; |
@@ -484,6 +510,29 @@ int arizona_dev_init(struct arizona *arizona) | |||
484 | goto err_reset; | 510 | goto err_reset; |
485 | } | 511 | } |
486 | 512 | ||
513 | for (i = 0; i < ARIZONA_MAX_MICBIAS; i++) { | ||
514 | if (!arizona->pdata.micbias[i].mV) | ||
515 | continue; | ||
516 | |||
517 | val = (arizona->pdata.micbias[i].mV - 1500) / 100; | ||
518 | val <<= ARIZONA_MICB1_LVL_SHIFT; | ||
519 | |||
520 | if (arizona->pdata.micbias[i].ext_cap) | ||
521 | val |= ARIZONA_MICB1_EXT_CAP; | ||
522 | |||
523 | if (arizona->pdata.micbias[i].discharge) | ||
524 | val |= ARIZONA_MICB1_DISCH; | ||
525 | |||
526 | if (arizona->pdata.micbias[i].fast_start) | ||
527 | val |= ARIZONA_MICB1_RATE; | ||
528 | |||
529 | regmap_update_bits(arizona->regmap, | ||
530 | ARIZONA_MIC_BIAS_CTRL_1 + i, | ||
531 | ARIZONA_MICB1_LVL_MASK | | ||
532 | ARIZONA_MICB1_DISCH | | ||
533 | ARIZONA_MICB1_RATE, val); | ||
534 | } | ||
535 | |||
487 | for (i = 0; i < ARIZONA_MAX_INPUT; i++) { | 536 | for (i = 0; i < ARIZONA_MAX_INPUT; i++) { |
488 | /* Default for both is 0 so noop with defaults */ | 537 | /* Default for both is 0 so noop with defaults */ |
489 | val = arizona->pdata.dmic_ref[i] | 538 | val = arizona->pdata.dmic_ref[i] |
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 885e56780358..6a9fec40d018 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c | |||
@@ -60,7 +60,7 @@ static inline bool i2c_safe_reg(unsigned char reg) | |||
60 | * This fix is to follow any read or write with a dummy read to a safe | 60 | * This fix is to follow any read or write with a dummy read to a safe |
61 | * register. | 61 | * register. |
62 | */ | 62 | */ |
63 | int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg) | 63 | static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg) |
64 | { | 64 | { |
65 | int val; | 65 | int val; |
66 | 66 | ||
@@ -85,7 +85,6 @@ int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg) | |||
85 | 85 | ||
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | EXPORT_SYMBOL(da9052_i2c_fix); | ||
89 | 88 | ||
90 | static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) | 89 | static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) |
91 | { | 90 | { |
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index a2bacf95b59e..21f261bf9e95 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/regulator/db8500-prcmu.h> | 33 | #include <linux/regulator/db8500-prcmu.h> |
34 | #include <linux/regulator/machine.h> | 34 | #include <linux/regulator/machine.h> |
35 | #include <linux/cpufreq.h> | 35 | #include <linux/cpufreq.h> |
36 | #include <linux/platform_data/ux500_wdt.h> | ||
36 | #include <mach/hardware.h> | 37 | #include <mach/hardware.h> |
37 | #include <mach/irqs.h> | 38 | #include <mach/irqs.h> |
38 | #include <mach/db8500-regs.h> | 39 | #include <mach/db8500-regs.h> |
@@ -2207,21 +2208,25 @@ int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | |||
2207 | sleep_auto_off ? A9WDOG_AUTO_OFF_EN : | 2208 | sleep_auto_off ? A9WDOG_AUTO_OFF_EN : |
2208 | A9WDOG_AUTO_OFF_DIS); | 2209 | A9WDOG_AUTO_OFF_DIS); |
2209 | } | 2210 | } |
2211 | EXPORT_SYMBOL(db8500_prcmu_config_a9wdog); | ||
2210 | 2212 | ||
2211 | int db8500_prcmu_enable_a9wdog(u8 id) | 2213 | int db8500_prcmu_enable_a9wdog(u8 id) |
2212 | { | 2214 | { |
2213 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); | 2215 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); |
2214 | } | 2216 | } |
2217 | EXPORT_SYMBOL(db8500_prcmu_enable_a9wdog); | ||
2215 | 2218 | ||
2216 | int db8500_prcmu_disable_a9wdog(u8 id) | 2219 | int db8500_prcmu_disable_a9wdog(u8 id) |
2217 | { | 2220 | { |
2218 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); | 2221 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); |
2219 | } | 2222 | } |
2223 | EXPORT_SYMBOL(db8500_prcmu_disable_a9wdog); | ||
2220 | 2224 | ||
2221 | int db8500_prcmu_kick_a9wdog(u8 id) | 2225 | int db8500_prcmu_kick_a9wdog(u8 id) |
2222 | { | 2226 | { |
2223 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); | 2227 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); |
2224 | } | 2228 | } |
2229 | EXPORT_SYMBOL(db8500_prcmu_kick_a9wdog); | ||
2225 | 2230 | ||
2226 | /* | 2231 | /* |
2227 | * timeout is 28 bit, in ms. | 2232 | * timeout is 28 bit, in ms. |
@@ -2239,6 +2244,7 @@ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout) | |||
2239 | (u8)((timeout >> 12) & 0xff), | 2244 | (u8)((timeout >> 12) & 0xff), |
2240 | (u8)((timeout >> 20) & 0xff)); | 2245 | (u8)((timeout >> 20) & 0xff)); |
2241 | } | 2246 | } |
2247 | EXPORT_SYMBOL(db8500_prcmu_load_a9wdog); | ||
2242 | 2248 | ||
2243 | /** | 2249 | /** |
2244 | * prcmu_abb_read() - Read register value(s) from the ABB. | 2250 | * prcmu_abb_read() - Read register value(s) from the ABB. |
@@ -3094,6 +3100,11 @@ static struct resource ab8500_resources[] = { | |||
3094 | } | 3100 | } |
3095 | }; | 3101 | }; |
3096 | 3102 | ||
3103 | static struct ux500_wdt_data db8500_wdt_pdata = { | ||
3104 | .timeout = 600, /* 10 minutes */ | ||
3105 | .has_28_bits_resolution = true, | ||
3106 | }; | ||
3107 | |||
3097 | static struct mfd_cell db8500_prcmu_devs[] = { | 3108 | static struct mfd_cell db8500_prcmu_devs[] = { |
3098 | { | 3109 | { |
3099 | .name = "db8500-prcmu-regulators", | 3110 | .name = "db8500-prcmu-regulators", |
@@ -3108,6 +3119,12 @@ static struct mfd_cell db8500_prcmu_devs[] = { | |||
3108 | .pdata_size = sizeof(db8500_cpufreq_table), | 3119 | .pdata_size = sizeof(db8500_cpufreq_table), |
3109 | }, | 3120 | }, |
3110 | { | 3121 | { |
3122 | .name = "ux500_wdt", | ||
3123 | .platform_data = &db8500_wdt_pdata, | ||
3124 | .pdata_size = sizeof(db8500_wdt_pdata), | ||
3125 | .id = -1, | ||
3126 | }, | ||
3127 | { | ||
3111 | .name = "ab8500-core", | 3128 | .name = "ab8500-core", |
3112 | .of_compatible = "stericsson,ab8500", | 3129 | .of_compatible = "stericsson,ab8500", |
3113 | .num_resources = ARRAY_SIZE(ab8500_resources), | 3130 | .num_resources = ARRAY_SIZE(ab8500_resources), |
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index d9d930302e98..9f12f91d6296 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c | |||
@@ -50,6 +50,7 @@ | |||
50 | * document number TBD : Panther Point | 50 | * document number TBD : Panther Point |
51 | * document number TBD : Lynx Point | 51 | * document number TBD : Lynx Point |
52 | * document number TBD : Lynx Point-LP | 52 | * document number TBD : Lynx Point-LP |
53 | * document number TBD : Wellsburg | ||
53 | */ | 54 | */ |
54 | 55 | ||
55 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 56 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
@@ -75,8 +76,10 @@ | |||
75 | #define ACPIBASE_GCS_OFF 0x3410 | 76 | #define ACPIBASE_GCS_OFF 0x3410 |
76 | #define ACPIBASE_GCS_END 0x3414 | 77 | #define ACPIBASE_GCS_END 0x3414 |
77 | 78 | ||
78 | #define GPIOBASE 0x48 | 79 | #define GPIOBASE_ICH0 0x58 |
79 | #define GPIOCTRL 0x4C | 80 | #define GPIOCTRL_ICH0 0x5C |
81 | #define GPIOBASE_ICH6 0x48 | ||
82 | #define GPIOCTRL_ICH6 0x4C | ||
80 | 83 | ||
81 | #define RCBABASE 0xf0 | 84 | #define RCBABASE 0xf0 |
82 | 85 | ||
@@ -84,8 +87,17 @@ | |||
84 | #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) | 87 | #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) |
85 | #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) | 88 | #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) |
86 | 89 | ||
87 | static int lpc_ich_acpi_save = -1; | 90 | struct lpc_ich_cfg { |
88 | static int lpc_ich_gpio_save = -1; | 91 | int base; |
92 | int ctrl; | ||
93 | int save; | ||
94 | }; | ||
95 | |||
96 | struct lpc_ich_priv { | ||
97 | int chipset; | ||
98 | struct lpc_ich_cfg acpi; | ||
99 | struct lpc_ich_cfg gpio; | ||
100 | }; | ||
89 | 101 | ||
90 | static struct resource wdt_ich_res[] = { | 102 | static struct resource wdt_ich_res[] = { |
91 | /* ACPI - TCO */ | 103 | /* ACPI - TCO */ |
@@ -194,6 +206,7 @@ enum lpc_chipsets { | |||
194 | LPC_PPT, /* Panther Point */ | 206 | LPC_PPT, /* Panther Point */ |
195 | LPC_LPT, /* Lynx Point */ | 207 | LPC_LPT, /* Lynx Point */ |
196 | LPC_LPT_LP, /* Lynx Point-LP */ | 208 | LPC_LPT_LP, /* Lynx Point-LP */ |
209 | LPC_WBG, /* Wellsburg */ | ||
197 | }; | 210 | }; |
198 | 211 | ||
199 | struct lpc_ich_info lpc_chipset_info[] = { | 212 | struct lpc_ich_info lpc_chipset_info[] = { |
@@ -474,6 +487,10 @@ struct lpc_ich_info lpc_chipset_info[] = { | |||
474 | .name = "Lynx Point_LP", | 487 | .name = "Lynx Point_LP", |
475 | .iTCO_version = 2, | 488 | .iTCO_version = 2, |
476 | }, | 489 | }, |
490 | [LPC_WBG] = { | ||
491 | .name = "Wellsburg", | ||
492 | .iTCO_version = 2, | ||
493 | }, | ||
477 | }; | 494 | }; |
478 | 495 | ||
479 | /* | 496 | /* |
@@ -655,45 +672,82 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = { | |||
655 | { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP}, | 672 | { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP}, |
656 | { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP}, | 673 | { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP}, |
657 | { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP}, | 674 | { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP}, |
675 | { PCI_VDEVICE(INTEL, 0x8d40), LPC_WBG}, | ||
676 | { PCI_VDEVICE(INTEL, 0x8d41), LPC_WBG}, | ||
677 | { PCI_VDEVICE(INTEL, 0x8d42), LPC_WBG}, | ||
678 | { PCI_VDEVICE(INTEL, 0x8d43), LPC_WBG}, | ||
679 | { PCI_VDEVICE(INTEL, 0x8d44), LPC_WBG}, | ||
680 | { PCI_VDEVICE(INTEL, 0x8d45), LPC_WBG}, | ||
681 | { PCI_VDEVICE(INTEL, 0x8d46), LPC_WBG}, | ||
682 | { PCI_VDEVICE(INTEL, 0x8d47), LPC_WBG}, | ||
683 | { PCI_VDEVICE(INTEL, 0x8d48), LPC_WBG}, | ||
684 | { PCI_VDEVICE(INTEL, 0x8d49), LPC_WBG}, | ||
685 | { PCI_VDEVICE(INTEL, 0x8d4a), LPC_WBG}, | ||
686 | { PCI_VDEVICE(INTEL, 0x8d4b), LPC_WBG}, | ||
687 | { PCI_VDEVICE(INTEL, 0x8d4c), LPC_WBG}, | ||
688 | { PCI_VDEVICE(INTEL, 0x8d4d), LPC_WBG}, | ||
689 | { PCI_VDEVICE(INTEL, 0x8d4e), LPC_WBG}, | ||
690 | { PCI_VDEVICE(INTEL, 0x8d4f), LPC_WBG}, | ||
691 | { PCI_VDEVICE(INTEL, 0x8d50), LPC_WBG}, | ||
692 | { PCI_VDEVICE(INTEL, 0x8d51), LPC_WBG}, | ||
693 | { PCI_VDEVICE(INTEL, 0x8d52), LPC_WBG}, | ||
694 | { PCI_VDEVICE(INTEL, 0x8d53), LPC_WBG}, | ||
695 | { PCI_VDEVICE(INTEL, 0x8d54), LPC_WBG}, | ||
696 | { PCI_VDEVICE(INTEL, 0x8d55), LPC_WBG}, | ||
697 | { PCI_VDEVICE(INTEL, 0x8d56), LPC_WBG}, | ||
698 | { PCI_VDEVICE(INTEL, 0x8d57), LPC_WBG}, | ||
699 | { PCI_VDEVICE(INTEL, 0x8d58), LPC_WBG}, | ||
700 | { PCI_VDEVICE(INTEL, 0x8d59), LPC_WBG}, | ||
701 | { PCI_VDEVICE(INTEL, 0x8d5a), LPC_WBG}, | ||
702 | { PCI_VDEVICE(INTEL, 0x8d5b), LPC_WBG}, | ||
703 | { PCI_VDEVICE(INTEL, 0x8d5c), LPC_WBG}, | ||
704 | { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG}, | ||
705 | { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG}, | ||
706 | { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG}, | ||
658 | { 0, }, /* End of list */ | 707 | { 0, }, /* End of list */ |
659 | }; | 708 | }; |
660 | MODULE_DEVICE_TABLE(pci, lpc_ich_ids); | 709 | MODULE_DEVICE_TABLE(pci, lpc_ich_ids); |
661 | 710 | ||
662 | static void lpc_ich_restore_config_space(struct pci_dev *dev) | 711 | static void lpc_ich_restore_config_space(struct pci_dev *dev) |
663 | { | 712 | { |
664 | if (lpc_ich_acpi_save >= 0) { | 713 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); |
665 | pci_write_config_byte(dev, ACPICTRL, lpc_ich_acpi_save); | 714 | |
666 | lpc_ich_acpi_save = -1; | 715 | if (priv->acpi.save >= 0) { |
716 | pci_write_config_byte(dev, priv->acpi.ctrl, priv->acpi.save); | ||
717 | priv->acpi.save = -1; | ||
667 | } | 718 | } |
668 | 719 | ||
669 | if (lpc_ich_gpio_save >= 0) { | 720 | if (priv->gpio.save >= 0) { |
670 | pci_write_config_byte(dev, GPIOCTRL, lpc_ich_gpio_save); | 721 | pci_write_config_byte(dev, priv->gpio.ctrl, priv->gpio.save); |
671 | lpc_ich_gpio_save = -1; | 722 | priv->gpio.save = -1; |
672 | } | 723 | } |
673 | } | 724 | } |
674 | 725 | ||
675 | static void lpc_ich_enable_acpi_space(struct pci_dev *dev) | 726 | static void lpc_ich_enable_acpi_space(struct pci_dev *dev) |
676 | { | 727 | { |
728 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
677 | u8 reg_save; | 729 | u8 reg_save; |
678 | 730 | ||
679 | pci_read_config_byte(dev, ACPICTRL, ®_save); | 731 | pci_read_config_byte(dev, priv->acpi.ctrl, ®_save); |
680 | pci_write_config_byte(dev, ACPICTRL, reg_save | 0x10); | 732 | pci_write_config_byte(dev, priv->acpi.ctrl, reg_save | 0x10); |
681 | lpc_ich_acpi_save = reg_save; | 733 | priv->acpi.save = reg_save; |
682 | } | 734 | } |
683 | 735 | ||
684 | static void lpc_ich_enable_gpio_space(struct pci_dev *dev) | 736 | static void lpc_ich_enable_gpio_space(struct pci_dev *dev) |
685 | { | 737 | { |
738 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
686 | u8 reg_save; | 739 | u8 reg_save; |
687 | 740 | ||
688 | pci_read_config_byte(dev, GPIOCTRL, ®_save); | 741 | pci_read_config_byte(dev, priv->gpio.ctrl, ®_save); |
689 | pci_write_config_byte(dev, GPIOCTRL, reg_save | 0x10); | 742 | pci_write_config_byte(dev, priv->gpio.ctrl, reg_save | 0x10); |
690 | lpc_ich_gpio_save = reg_save; | 743 | priv->gpio.save = reg_save; |
691 | } | 744 | } |
692 | 745 | ||
693 | static void lpc_ich_finalize_cell(struct mfd_cell *cell, | 746 | static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell) |
694 | const struct pci_device_id *id) | ||
695 | { | 747 | { |
696 | cell->platform_data = &lpc_chipset_info[id->driver_data]; | 748 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); |
749 | |||
750 | cell->platform_data = &lpc_chipset_info[priv->chipset]; | ||
697 | cell->pdata_size = sizeof(struct lpc_ich_info); | 751 | cell->pdata_size = sizeof(struct lpc_ich_info); |
698 | } | 752 | } |
699 | 753 | ||
@@ -721,9 +775,9 @@ static int lpc_ich_check_conflict_gpio(struct resource *res) | |||
721 | return use_gpio ? use_gpio : ret; | 775 | return use_gpio ? use_gpio : ret; |
722 | } | 776 | } |
723 | 777 | ||
724 | static int lpc_ich_init_gpio(struct pci_dev *dev, | 778 | static int lpc_ich_init_gpio(struct pci_dev *dev) |
725 | const struct pci_device_id *id) | ||
726 | { | 779 | { |
780 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
727 | u32 base_addr_cfg; | 781 | u32 base_addr_cfg; |
728 | u32 base_addr; | 782 | u32 base_addr; |
729 | int ret; | 783 | int ret; |
@@ -731,7 +785,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev, | |||
731 | struct resource *res; | 785 | struct resource *res; |
732 | 786 | ||
733 | /* Setup power management base register */ | 787 | /* Setup power management base register */ |
734 | pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg); | 788 | pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg); |
735 | base_addr = base_addr_cfg & 0x0000ff80; | 789 | base_addr = base_addr_cfg & 0x0000ff80; |
736 | if (!base_addr) { | 790 | if (!base_addr) { |
737 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); | 791 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); |
@@ -757,7 +811,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev, | |||
757 | 811 | ||
758 | gpe0_done: | 812 | gpe0_done: |
759 | /* Setup GPIO base register */ | 813 | /* Setup GPIO base register */ |
760 | pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); | 814 | pci_read_config_dword(dev, priv->gpio.base, &base_addr_cfg); |
761 | base_addr = base_addr_cfg & 0x0000ff80; | 815 | base_addr = base_addr_cfg & 0x0000ff80; |
762 | if (!base_addr) { | 816 | if (!base_addr) { |
763 | dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); | 817 | dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); |
@@ -768,7 +822,7 @@ gpe0_done: | |||
768 | /* Older devices provide fewer GPIO and have a smaller resource size. */ | 822 | /* Older devices provide fewer GPIO and have a smaller resource size. */ |
769 | res = &gpio_ich_res[ICH_RES_GPIO]; | 823 | res = &gpio_ich_res[ICH_RES_GPIO]; |
770 | res->start = base_addr; | 824 | res->start = base_addr; |
771 | switch (lpc_chipset_info[id->driver_data].gpio_version) { | 825 | switch (lpc_chipset_info[priv->chipset].gpio_version) { |
772 | case ICH_V5_GPIO: | 826 | case ICH_V5_GPIO: |
773 | case ICH_V10CORP_GPIO: | 827 | case ICH_V10CORP_GPIO: |
774 | res->end = res->start + 128 - 1; | 828 | res->end = res->start + 128 - 1; |
@@ -784,10 +838,10 @@ gpe0_done: | |||
784 | acpi_conflict = true; | 838 | acpi_conflict = true; |
785 | goto gpio_done; | 839 | goto gpio_done; |
786 | } | 840 | } |
787 | lpc_chipset_info[id->driver_data].use_gpio = ret; | 841 | lpc_chipset_info[priv->chipset].use_gpio = ret; |
788 | lpc_ich_enable_gpio_space(dev); | 842 | lpc_ich_enable_gpio_space(dev); |
789 | 843 | ||
790 | lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id); | 844 | lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_GPIO]); |
791 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], | 845 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], |
792 | 1, NULL, 0, NULL); | 846 | 1, NULL, 0, NULL); |
793 | 847 | ||
@@ -798,16 +852,16 @@ gpio_done: | |||
798 | return ret; | 852 | return ret; |
799 | } | 853 | } |
800 | 854 | ||
801 | static int lpc_ich_init_wdt(struct pci_dev *dev, | 855 | static int lpc_ich_init_wdt(struct pci_dev *dev) |
802 | const struct pci_device_id *id) | ||
803 | { | 856 | { |
857 | struct lpc_ich_priv *priv = pci_get_drvdata(dev); | ||
804 | u32 base_addr_cfg; | 858 | u32 base_addr_cfg; |
805 | u32 base_addr; | 859 | u32 base_addr; |
806 | int ret; | 860 | int ret; |
807 | struct resource *res; | 861 | struct resource *res; |
808 | 862 | ||
809 | /* Setup power management base register */ | 863 | /* Setup power management base register */ |
810 | pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg); | 864 | pci_read_config_dword(dev, priv->acpi.base, &base_addr_cfg); |
811 | base_addr = base_addr_cfg & 0x0000ff80; | 865 | base_addr = base_addr_cfg & 0x0000ff80; |
812 | if (!base_addr) { | 866 | if (!base_addr) { |
813 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); | 867 | dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); |
@@ -830,7 +884,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev, | |||
830 | * we have to read RCBA from PCI Config space 0xf0 and use | 884 | * we have to read RCBA from PCI Config space 0xf0 and use |
831 | * it as base. GCS = RCBA + ICH6_GCS(0x3410). | 885 | * it as base. GCS = RCBA + ICH6_GCS(0x3410). |
832 | */ | 886 | */ |
833 | if (lpc_chipset_info[id->driver_data].iTCO_version == 1) { | 887 | if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { |
834 | /* Don't register iomem for TCO ver 1 */ | 888 | /* Don't register iomem for TCO ver 1 */ |
835 | lpc_ich_cells[LPC_WDT].num_resources--; | 889 | lpc_ich_cells[LPC_WDT].num_resources--; |
836 | } else { | 890 | } else { |
@@ -847,7 +901,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev, | |||
847 | res->end = base_addr + ACPIBASE_GCS_END; | 901 | res->end = base_addr + ACPIBASE_GCS_END; |
848 | } | 902 | } |
849 | 903 | ||
850 | lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); | 904 | lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]); |
851 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], | 905 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], |
852 | 1, NULL, 0, NULL); | 906 | 1, NULL, 0, NULL); |
853 | 907 | ||
@@ -858,14 +912,36 @@ wdt_done: | |||
858 | static int lpc_ich_probe(struct pci_dev *dev, | 912 | static int lpc_ich_probe(struct pci_dev *dev, |
859 | const struct pci_device_id *id) | 913 | const struct pci_device_id *id) |
860 | { | 914 | { |
915 | struct lpc_ich_priv *priv; | ||
861 | int ret; | 916 | int ret; |
862 | bool cell_added = false; | 917 | bool cell_added = false; |
863 | 918 | ||
864 | ret = lpc_ich_init_wdt(dev, id); | 919 | priv = devm_kzalloc(&dev->dev, |
920 | sizeof(struct lpc_ich_priv), GFP_KERNEL); | ||
921 | if (!priv) | ||
922 | return -ENOMEM; | ||
923 | |||
924 | priv->chipset = id->driver_data; | ||
925 | priv->acpi.save = -1; | ||
926 | priv->acpi.base = ACPIBASE; | ||
927 | priv->acpi.ctrl = ACPICTRL; | ||
928 | |||
929 | priv->gpio.save = -1; | ||
930 | if (priv->chipset <= LPC_ICH5) { | ||
931 | priv->gpio.base = GPIOBASE_ICH0; | ||
932 | priv->gpio.ctrl = GPIOCTRL_ICH0; | ||
933 | } else { | ||
934 | priv->gpio.base = GPIOBASE_ICH6; | ||
935 | priv->gpio.ctrl = GPIOCTRL_ICH6; | ||
936 | } | ||
937 | |||
938 | pci_set_drvdata(dev, priv); | ||
939 | |||
940 | ret = lpc_ich_init_wdt(dev); | ||
865 | if (!ret) | 941 | if (!ret) |
866 | cell_added = true; | 942 | cell_added = true; |
867 | 943 | ||
868 | ret = lpc_ich_init_gpio(dev, id); | 944 | ret = lpc_ich_init_gpio(dev); |
869 | if (!ret) | 945 | if (!ret) |
870 | cell_added = true; | 946 | cell_added = true; |
871 | 947 | ||
@@ -876,6 +952,7 @@ static int lpc_ich_probe(struct pci_dev *dev, | |||
876 | if (!cell_added) { | 952 | if (!cell_added) { |
877 | dev_warn(&dev->dev, "No MFD cells added\n"); | 953 | dev_warn(&dev->dev, "No MFD cells added\n"); |
878 | lpc_ich_restore_config_space(dev); | 954 | lpc_ich_restore_config_space(dev); |
955 | pci_set_drvdata(dev, NULL); | ||
879 | return -ENODEV; | 956 | return -ENODEV; |
880 | } | 957 | } |
881 | 958 | ||
@@ -886,6 +963,7 @@ static void lpc_ich_remove(struct pci_dev *dev) | |||
886 | { | 963 | { |
887 | mfd_remove_devices(&dev->dev); | 964 | mfd_remove_devices(&dev->dev); |
888 | lpc_ich_restore_config_space(dev); | 965 | lpc_ich_restore_config_space(dev); |
966 | pci_set_drvdata(dev, NULL); | ||
889 | } | 967 | } |
890 | 968 | ||
891 | static struct pci_driver lpc_ich_driver = { | 969 | static struct pci_driver lpc_ich_driver = { |
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index 5624fcbba69b..8cc6aac27cb2 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c | |||
@@ -45,34 +45,32 @@ static struct resource smbus_sch_resource = { | |||
45 | .flags = IORESOURCE_IO, | 45 | .flags = IORESOURCE_IO, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | |||
49 | static struct resource gpio_sch_resource = { | 48 | static struct resource gpio_sch_resource = { |
50 | .flags = IORESOURCE_IO, | 49 | .flags = IORESOURCE_IO, |
51 | }; | 50 | }; |
52 | 51 | ||
53 | static struct mfd_cell lpc_sch_cells[] = { | ||
54 | { | ||
55 | .name = "isch_smbus", | ||
56 | .num_resources = 1, | ||
57 | .resources = &smbus_sch_resource, | ||
58 | }, | ||
59 | { | ||
60 | .name = "sch_gpio", | ||
61 | .num_resources = 1, | ||
62 | .resources = &gpio_sch_resource, | ||
63 | }, | ||
64 | }; | ||
65 | |||
66 | static struct resource wdt_sch_resource = { | 52 | static struct resource wdt_sch_resource = { |
67 | .flags = IORESOURCE_IO, | 53 | .flags = IORESOURCE_IO, |
68 | }; | 54 | }; |
69 | 55 | ||
70 | static struct mfd_cell tunnelcreek_cells[] = { | 56 | static struct mfd_cell lpc_sch_cells[3]; |
71 | { | 57 | |
72 | .name = "ie6xx_wdt", | 58 | static struct mfd_cell isch_smbus_cell = { |
73 | .num_resources = 1, | 59 | .name = "isch_smbus", |
74 | .resources = &wdt_sch_resource, | 60 | .num_resources = 1, |
75 | }, | 61 | .resources = &smbus_sch_resource, |
62 | }; | ||
63 | |||
64 | static struct mfd_cell sch_gpio_cell = { | ||
65 | .name = "sch_gpio", | ||
66 | .num_resources = 1, | ||
67 | .resources = &gpio_sch_resource, | ||
68 | }; | ||
69 | |||
70 | static struct mfd_cell wdt_sch_cell = { | ||
71 | .name = "ie6xx_wdt", | ||
72 | .num_resources = 1, | ||
73 | .resources = &wdt_sch_resource, | ||
76 | }; | 74 | }; |
77 | 75 | ||
78 | static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = { | 76 | static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = { |
@@ -88,79 +86,76 @@ static int lpc_sch_probe(struct pci_dev *dev, | |||
88 | { | 86 | { |
89 | unsigned int base_addr_cfg; | 87 | unsigned int base_addr_cfg; |
90 | unsigned short base_addr; | 88 | unsigned short base_addr; |
91 | int i; | 89 | int i, cells = 0; |
92 | int ret; | 90 | int ret; |
93 | 91 | ||
94 | pci_read_config_dword(dev, SMBASE, &base_addr_cfg); | 92 | pci_read_config_dword(dev, SMBASE, &base_addr_cfg); |
95 | if (!(base_addr_cfg & (1 << 31))) { | 93 | base_addr = 0; |
96 | dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n"); | 94 | if (!(base_addr_cfg & (1 << 31))) |
97 | return -ENODEV; | 95 | dev_warn(&dev->dev, "Decode of the SMBus I/O range disabled\n"); |
98 | } | 96 | else |
99 | base_addr = (unsigned short)base_addr_cfg; | 97 | base_addr = (unsigned short)base_addr_cfg; |
100 | if (base_addr == 0) { | ||
101 | dev_err(&dev->dev, "I/O space for SMBus uninitialized\n"); | ||
102 | return -ENODEV; | ||
103 | } | ||
104 | |||
105 | smbus_sch_resource.start = base_addr; | ||
106 | smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1; | ||
107 | 98 | ||
108 | pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); | ||
109 | if (!(base_addr_cfg & (1 << 31))) { | ||
110 | dev_err(&dev->dev, "Decode of the GPIO I/O range disabled\n"); | ||
111 | return -ENODEV; | ||
112 | } | ||
113 | base_addr = (unsigned short)base_addr_cfg; | ||
114 | if (base_addr == 0) { | 99 | if (base_addr == 0) { |
115 | dev_err(&dev->dev, "I/O space for GPIO uninitialized\n"); | 100 | dev_warn(&dev->dev, "I/O space for SMBus uninitialized\n"); |
116 | return -ENODEV; | 101 | } else { |
102 | lpc_sch_cells[cells++] = isch_smbus_cell; | ||
103 | smbus_sch_resource.start = base_addr; | ||
104 | smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1; | ||
117 | } | 105 | } |
118 | 106 | ||
119 | gpio_sch_resource.start = base_addr; | 107 | pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); |
120 | 108 | base_addr = 0; | |
121 | if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) | 109 | if (!(base_addr_cfg & (1 << 31))) |
122 | gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1; | 110 | dev_warn(&dev->dev, "Decode of the GPIO I/O range disabled\n"); |
123 | else | 111 | else |
124 | gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; | 112 | base_addr = (unsigned short)base_addr_cfg; |
125 | |||
126 | for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++) | ||
127 | lpc_sch_cells[i].id = id->device; | ||
128 | 113 | ||
129 | ret = mfd_add_devices(&dev->dev, 0, | 114 | if (base_addr == 0) { |
130 | lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, | 115 | dev_warn(&dev->dev, "I/O space for GPIO uninitialized\n"); |
131 | 0, NULL); | 116 | } else { |
132 | if (ret) | 117 | lpc_sch_cells[cells++] = sch_gpio_cell; |
133 | goto out_dev; | 118 | gpio_sch_resource.start = base_addr; |
119 | if (id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) | ||
120 | gpio_sch_resource.end = base_addr + GPIO_IO_SIZE_CENTERTON - 1; | ||
121 | else | ||
122 | gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; | ||
123 | } | ||
134 | 124 | ||
135 | if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC | 125 | if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC |
136 | || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) { | 126 | || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) { |
137 | pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); | 127 | pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); |
138 | if (!(base_addr_cfg & (1 << 31))) { | 128 | base_addr = 0; |
139 | dev_err(&dev->dev, "Decode of the WDT I/O range disabled\n"); | 129 | if (!(base_addr_cfg & (1 << 31))) |
140 | ret = -ENODEV; | 130 | dev_warn(&dev->dev, "Decode of the WDT I/O range disabled\n"); |
141 | goto out_dev; | 131 | else |
132 | base_addr = (unsigned short)base_addr_cfg; | ||
133 | if (base_addr == 0) | ||
134 | dev_warn(&dev->dev, "I/O space for WDT uninitialized\n"); | ||
135 | else { | ||
136 | lpc_sch_cells[cells++] = wdt_sch_cell; | ||
137 | wdt_sch_resource.start = base_addr; | ||
138 | wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1; | ||
142 | } | 139 | } |
143 | base_addr = (unsigned short)base_addr_cfg; | 140 | } |
144 | if (base_addr == 0) { | ||
145 | dev_err(&dev->dev, "I/O space for WDT uninitialized\n"); | ||
146 | ret = -ENODEV; | ||
147 | goto out_dev; | ||
148 | } | ||
149 | |||
150 | wdt_sch_resource.start = base_addr; | ||
151 | wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1; | ||
152 | 141 | ||
153 | for (i = 0; i < ARRAY_SIZE(tunnelcreek_cells); i++) | 142 | if (WARN_ON(cells > ARRAY_SIZE(lpc_sch_cells))) { |
154 | tunnelcreek_cells[i].id = id->device; | 143 | dev_err(&dev->dev, "Cell count exceeds array size"); |
144 | return -ENODEV; | ||
145 | } | ||
155 | 146 | ||
156 | ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, | 147 | if (cells == 0) { |
157 | ARRAY_SIZE(tunnelcreek_cells), NULL, | 148 | dev_err(&dev->dev, "All decode registers disabled.\n"); |
158 | 0, NULL); | 149 | return -ENODEV; |
159 | } | 150 | } |
160 | 151 | ||
161 | return ret; | 152 | for (i = 0; i < cells; i++) |
162 | out_dev: | 153 | lpc_sch_cells[i].id = id->device; |
163 | mfd_remove_devices(&dev->dev); | 154 | |
155 | ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL); | ||
156 | if (ret) | ||
157 | mfd_remove_devices(&dev->dev); | ||
158 | |||
164 | return ret; | 159 | return ret; |
165 | } | 160 | } |
166 | 161 | ||
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index e32466e865b9..f0cc40296d8c 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -14,10 +14,13 @@ | |||
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/irqdomain.h> | ||
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | #include <linux/regulator/machine.h> | 19 | #include <linux/regulator/machine.h> |
19 | #include <linux/mfd/core.h> | 20 | #include <linux/mfd/core.h> |
20 | #include <linux/mfd/max8925.h> | 21 | #include <linux/mfd/max8925.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_platform.h> | ||
21 | 24 | ||
22 | static struct resource bk_resources[] = { | 25 | static struct resource bk_resources[] = { |
23 | { 0x84, 0x84, "mode control", IORESOURCE_REG, }, | 26 | { 0x84, 0x84, "mode control", IORESOURCE_REG, }, |
@@ -639,17 +642,33 @@ static struct irq_chip max8925_irq_chip = { | |||
639 | .irq_disable = max8925_irq_disable, | 642 | .irq_disable = max8925_irq_disable, |
640 | }; | 643 | }; |
641 | 644 | ||
645 | static int max8925_irq_domain_map(struct irq_domain *d, unsigned int virq, | ||
646 | irq_hw_number_t hw) | ||
647 | { | ||
648 | irq_set_chip_data(virq, d->host_data); | ||
649 | irq_set_chip_and_handler(virq, &max8925_irq_chip, handle_edge_irq); | ||
650 | irq_set_nested_thread(virq, 1); | ||
651 | #ifdef CONFIG_ARM | ||
652 | set_irq_flags(virq, IRQF_VALID); | ||
653 | #else | ||
654 | irq_set_noprobe(virq); | ||
655 | #endif | ||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static struct irq_domain_ops max8925_irq_domain_ops = { | ||
660 | .map = max8925_irq_domain_map, | ||
661 | .xlate = irq_domain_xlate_onetwocell, | ||
662 | }; | ||
663 | |||
664 | |||
642 | static int max8925_irq_init(struct max8925_chip *chip, int irq, | 665 | static int max8925_irq_init(struct max8925_chip *chip, int irq, |
643 | struct max8925_platform_data *pdata) | 666 | struct max8925_platform_data *pdata) |
644 | { | 667 | { |
645 | unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; | 668 | unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; |
646 | int i, ret; | 669 | int ret; |
647 | int __irq; | 670 | struct device_node *node = chip->dev->of_node; |
648 | 671 | ||
649 | if (!pdata || !pdata->irq_base) { | ||
650 | dev_warn(chip->dev, "No interrupt support on IRQ base\n"); | ||
651 | return -EINVAL; | ||
652 | } | ||
653 | /* clear all interrupts */ | 672 | /* clear all interrupts */ |
654 | max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1); | 673 | max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1); |
655 | max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2); | 674 | max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2); |
@@ -667,35 +686,30 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq, | |||
667 | max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); | 686 | max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); |
668 | 687 | ||
669 | mutex_init(&chip->irq_lock); | 688 | mutex_init(&chip->irq_lock); |
670 | chip->core_irq = irq; | 689 | chip->irq_base = irq_alloc_descs(-1, 0, MAX8925_NR_IRQS, 0); |
671 | chip->irq_base = pdata->irq_base; | 690 | if (chip->irq_base < 0) { |
672 | 691 | dev_err(chip->dev, "Failed to allocate interrupts, ret:%d\n", | |
673 | /* register with genirq */ | 692 | chip->irq_base); |
674 | for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { | 693 | return -EBUSY; |
675 | __irq = i + chip->irq_base; | ||
676 | irq_set_chip_data(__irq, chip); | ||
677 | irq_set_chip_and_handler(__irq, &max8925_irq_chip, | ||
678 | handle_edge_irq); | ||
679 | irq_set_nested_thread(__irq, 1); | ||
680 | #ifdef CONFIG_ARM | ||
681 | set_irq_flags(__irq, IRQF_VALID); | ||
682 | #else | ||
683 | irq_set_noprobe(__irq); | ||
684 | #endif | ||
685 | } | ||
686 | if (!irq) { | ||
687 | dev_warn(chip->dev, "No interrupt support on core IRQ\n"); | ||
688 | goto tsc_irq; | ||
689 | } | 694 | } |
690 | 695 | ||
696 | irq_domain_add_legacy(node, MAX8925_NR_IRQS, chip->irq_base, 0, | ||
697 | &max8925_irq_domain_ops, chip); | ||
698 | |||
699 | /* request irq handler for pmic main irq*/ | ||
700 | chip->core_irq = irq; | ||
701 | if (!chip->core_irq) | ||
702 | return -EBUSY; | ||
691 | ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT, | 703 | ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT, |
692 | "max8925", chip); | 704 | "max8925", chip); |
693 | if (ret) { | 705 | if (ret) { |
694 | dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); | 706 | dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); |
695 | chip->core_irq = 0; | 707 | chip->core_irq = 0; |
708 | return -EBUSY; | ||
696 | } | 709 | } |
697 | 710 | ||
698 | tsc_irq: | 711 | /* request irq handler for pmic tsc irq*/ |
712 | |||
699 | /* mask TSC interrupt */ | 713 | /* mask TSC interrupt */ |
700 | max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f); | 714 | max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f); |
701 | 715 | ||
@@ -704,7 +718,6 @@ tsc_irq: | |||
704 | return 0; | 718 | return 0; |
705 | } | 719 | } |
706 | chip->tsc_irq = pdata->tsc_irq; | 720 | chip->tsc_irq = pdata->tsc_irq; |
707 | |||
708 | ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq, | 721 | ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq, |
709 | flags | IRQF_ONESHOT, "max8925-tsc", chip); | 722 | flags | IRQF_ONESHOT, "max8925-tsc", chip); |
710 | if (ret) { | 723 | if (ret) { |
@@ -846,7 +859,7 @@ int max8925_device_init(struct max8925_chip *chip, | |||
846 | 859 | ||
847 | ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], | 860 | ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], |
848 | ARRAY_SIZE(rtc_devs), | 861 | ARRAY_SIZE(rtc_devs), |
849 | &rtc_resources[0], chip->irq_base, NULL); | 862 | NULL, chip->irq_base, NULL); |
850 | if (ret < 0) { | 863 | if (ret < 0) { |
851 | dev_err(chip->dev, "Failed to add rtc subdev\n"); | 864 | dev_err(chip->dev, "Failed to add rtc subdev\n"); |
852 | goto out; | 865 | goto out; |
@@ -854,7 +867,7 @@ int max8925_device_init(struct max8925_chip *chip, | |||
854 | 867 | ||
855 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | 868 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], |
856 | ARRAY_SIZE(onkey_devs), | 869 | ARRAY_SIZE(onkey_devs), |
857 | &onkey_resources[0], 0, NULL); | 870 | NULL, chip->irq_base, NULL); |
858 | if (ret < 0) { | 871 | if (ret < 0) { |
859 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | 872 | dev_err(chip->dev, "Failed to add onkey subdev\n"); |
860 | goto out_dev; | 873 | goto out_dev; |
@@ -873,21 +886,19 @@ int max8925_device_init(struct max8925_chip *chip, | |||
873 | goto out_dev; | 886 | goto out_dev; |
874 | } | 887 | } |
875 | 888 | ||
876 | if (pdata && pdata->power) { | 889 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], |
877 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], | 890 | ARRAY_SIZE(power_devs), |
878 | ARRAY_SIZE(power_devs), | 891 | NULL, 0, NULL); |
879 | &power_supply_resources[0], 0, NULL); | 892 | if (ret < 0) { |
880 | if (ret < 0) { | 893 | dev_err(chip->dev, |
881 | dev_err(chip->dev, "Failed to add power supply " | 894 | "Failed to add power supply subdev, err = %d\n", ret); |
882 | "subdev\n"); | 895 | goto out_dev; |
883 | goto out_dev; | ||
884 | } | ||
885 | } | 896 | } |
886 | 897 | ||
887 | if (pdata && pdata->touch) { | 898 | if (pdata && pdata->touch) { |
888 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], | 899 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], |
889 | ARRAY_SIZE(touch_devs), | 900 | ARRAY_SIZE(touch_devs), |
890 | &touch_resources[0], 0, NULL); | 901 | NULL, chip->tsc_irq, NULL); |
891 | if (ret < 0) { | 902 | if (ret < 0) { |
892 | dev_err(chip->dev, "Failed to add touch subdev\n"); | 903 | dev_err(chip->dev, "Failed to add touch subdev\n"); |
893 | goto out_dev; | 904 | goto out_dev; |
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index 00b5b456063d..92bbebd31598 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c | |||
@@ -135,13 +135,37 @@ static const struct i2c_device_id max8925_id_table[] = { | |||
135 | }; | 135 | }; |
136 | MODULE_DEVICE_TABLE(i2c, max8925_id_table); | 136 | MODULE_DEVICE_TABLE(i2c, max8925_id_table); |
137 | 137 | ||
138 | static int max8925_dt_init(struct device_node *np, struct device *dev, | ||
139 | struct max8925_platform_data *pdata) | ||
140 | { | ||
141 | int ret; | ||
142 | |||
143 | ret = of_property_read_u32(np, "maxim,tsc-irq", &pdata->tsc_irq); | ||
144 | if (ret) { | ||
145 | dev_err(dev, "Not found maxim,tsc-irq property\n"); | ||
146 | return -EINVAL; | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | |||
138 | static int max8925_probe(struct i2c_client *client, | 151 | static int max8925_probe(struct i2c_client *client, |
139 | const struct i2c_device_id *id) | 152 | const struct i2c_device_id *id) |
140 | { | 153 | { |
141 | struct max8925_platform_data *pdata = client->dev.platform_data; | 154 | struct max8925_platform_data *pdata = client->dev.platform_data; |
142 | static struct max8925_chip *chip; | 155 | static struct max8925_chip *chip; |
143 | 156 | struct device_node *node = client->dev.of_node; | |
144 | if (!pdata) { | 157 | |
158 | if (node && !pdata) { | ||
159 | /* parse DT to get platform data */ | ||
160 | pdata = devm_kzalloc(&client->dev, | ||
161 | sizeof(struct max8925_platform_data), | ||
162 | GFP_KERNEL); | ||
163 | if (!pdata) | ||
164 | return -ENOMEM; | ||
165 | |||
166 | if (max8925_dt_init(node, &client->dev, pdata)) | ||
167 | return -EINVAL; | ||
168 | } else if (!pdata) { | ||
145 | pr_info("%s: platform data is missing\n", __func__); | 169 | pr_info("%s: platform data is missing\n", __func__); |
146 | return -EINVAL; | 170 | return -EINVAL; |
147 | } | 171 | } |
@@ -203,11 +227,18 @@ static int max8925_resume(struct device *dev) | |||
203 | 227 | ||
204 | static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume); | 228 | static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume); |
205 | 229 | ||
230 | static const struct of_device_id max8925_dt_ids[] = { | ||
231 | { .compatible = "maxim,max8925", }, | ||
232 | {}, | ||
233 | }; | ||
234 | MODULE_DEVICE_TABLE(of, max8925_dt_ids); | ||
235 | |||
206 | static struct i2c_driver max8925_driver = { | 236 | static struct i2c_driver max8925_driver = { |
207 | .driver = { | 237 | .driver = { |
208 | .name = "max8925", | 238 | .name = "max8925", |
209 | .owner = THIS_MODULE, | 239 | .owner = THIS_MODULE, |
210 | .pm = &max8925_pm_ops, | 240 | .pm = &max8925_pm_ops, |
241 | .of_match_table = of_match_ptr(max8925_dt_ids), | ||
211 | }, | 242 | }, |
212 | .probe = max8925_probe, | 243 | .probe = max8925_probe, |
213 | .remove = max8925_remove, | 244 | .remove = max8925_remove, |
@@ -217,7 +248,6 @@ static struct i2c_driver max8925_driver = { | |||
217 | static int __init max8925_i2c_init(void) | 248 | static int __init max8925_i2c_init(void) |
218 | { | 249 | { |
219 | int ret; | 250 | int ret; |
220 | |||
221 | ret = i2c_add_driver(&max8925_driver); | 251 | ret = i2c_add_driver(&max8925_driver); |
222 | if (ret != 0) | 252 | if (ret != 0) |
223 | pr_err("Failed to register MAX8925 I2C driver: %d\n", ret); | 253 | pr_err("Failed to register MAX8925 I2C driver: %d\n", ret); |
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 05164d7f054b..6b5edf64de2b 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
28 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
29 | #include <linux/platform_data/usb-omap.h> | 28 | #include <linux/platform_data/usb-omap.h> |
@@ -91,21 +90,23 @@ | |||
91 | 90 | ||
92 | 91 | ||
93 | struct usbhs_hcd_omap { | 92 | struct usbhs_hcd_omap { |
93 | int nports; | ||
94 | struct clk **utmi_clk; | ||
95 | struct clk **hsic60m_clk; | ||
96 | struct clk **hsic480m_clk; | ||
97 | |||
94 | struct clk *xclk60mhsp1_ck; | 98 | struct clk *xclk60mhsp1_ck; |
95 | struct clk *xclk60mhsp2_ck; | 99 | struct clk *xclk60mhsp2_ck; |
96 | struct clk *utmi_p1_fck; | 100 | struct clk *utmi_p1_gfclk; |
97 | struct clk *usbhost_p1_fck; | 101 | struct clk *utmi_p2_gfclk; |
98 | struct clk *utmi_p2_fck; | ||
99 | struct clk *usbhost_p2_fck; | ||
100 | struct clk *init_60m_fclk; | 102 | struct clk *init_60m_fclk; |
101 | struct clk *ehci_logic_fck; | 103 | struct clk *ehci_logic_fck; |
102 | 104 | ||
103 | void __iomem *uhh_base; | 105 | void __iomem *uhh_base; |
104 | 106 | ||
105 | struct usbhs_omap_platform_data platdata; | 107 | struct usbhs_omap_platform_data *pdata; |
106 | 108 | ||
107 | u32 usbhs_rev; | 109 | u32 usbhs_rev; |
108 | spinlock_t lock; | ||
109 | }; | 110 | }; |
110 | /*-------------------------------------------------------------------------*/ | 111 | /*-------------------------------------------------------------------------*/ |
111 | 112 | ||
@@ -184,19 +185,13 @@ err_end: | |||
184 | static int omap_usbhs_alloc_children(struct platform_device *pdev) | 185 | static int omap_usbhs_alloc_children(struct platform_device *pdev) |
185 | { | 186 | { |
186 | struct device *dev = &pdev->dev; | 187 | struct device *dev = &pdev->dev; |
187 | struct usbhs_hcd_omap *omap; | 188 | struct usbhs_omap_platform_data *pdata = dev->platform_data; |
188 | struct ehci_hcd_omap_platform_data *ehci_data; | ||
189 | struct ohci_hcd_omap_platform_data *ohci_data; | ||
190 | struct platform_device *ehci; | 189 | struct platform_device *ehci; |
191 | struct platform_device *ohci; | 190 | struct platform_device *ohci; |
192 | struct resource *res; | 191 | struct resource *res; |
193 | struct resource resources[2]; | 192 | struct resource resources[2]; |
194 | int ret; | 193 | int ret; |
195 | 194 | ||
196 | omap = platform_get_drvdata(pdev); | ||
197 | ehci_data = omap->platdata.ehci_data; | ||
198 | ohci_data = omap->platdata.ohci_data; | ||
199 | |||
200 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci"); | 195 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci"); |
201 | if (!res) { | 196 | if (!res) { |
202 | dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n"); | 197 | dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n"); |
@@ -213,8 +208,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) | |||
213 | } | 208 | } |
214 | resources[1] = *res; | 209 | resources[1] = *res; |
215 | 210 | ||
216 | ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, ehci_data, | 211 | ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, pdata, |
217 | sizeof(*ehci_data), dev); | 212 | sizeof(*pdata), dev); |
218 | 213 | ||
219 | if (!ehci) { | 214 | if (!ehci) { |
220 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); | 215 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); |
@@ -238,8 +233,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) | |||
238 | } | 233 | } |
239 | resources[1] = *res; | 234 | resources[1] = *res; |
240 | 235 | ||
241 | ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, ohci_data, | 236 | ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, pdata, |
242 | sizeof(*ohci_data), dev); | 237 | sizeof(*pdata), dev); |
243 | if (!ohci) { | 238 | if (!ohci) { |
244 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); | 239 | dev_err(dev, "omap_usbhs_alloc_child failed\n"); |
245 | ret = -ENOMEM; | 240 | ret = -ENOMEM; |
@@ -278,31 +273,52 @@ static bool is_ohci_port(enum usbhs_omap_port_mode pmode) | |||
278 | static int usbhs_runtime_resume(struct device *dev) | 273 | static int usbhs_runtime_resume(struct device *dev) |
279 | { | 274 | { |
280 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | 275 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); |
281 | struct usbhs_omap_platform_data *pdata = &omap->platdata; | 276 | struct usbhs_omap_platform_data *pdata = omap->pdata; |
282 | unsigned long flags; | 277 | int i, r; |
283 | 278 | ||
284 | dev_dbg(dev, "usbhs_runtime_resume\n"); | 279 | dev_dbg(dev, "usbhs_runtime_resume\n"); |
285 | 280 | ||
286 | if (!pdata) { | ||
287 | dev_dbg(dev, "missing platform_data\n"); | ||
288 | return -ENODEV; | ||
289 | } | ||
290 | |||
291 | omap_tll_enable(); | 281 | omap_tll_enable(); |
292 | spin_lock_irqsave(&omap->lock, flags); | ||
293 | 282 | ||
294 | if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) | 283 | if (!IS_ERR(omap->ehci_logic_fck)) |
295 | clk_enable(omap->ehci_logic_fck); | 284 | clk_enable(omap->ehci_logic_fck); |
296 | 285 | ||
297 | if (is_ehci_tll_mode(pdata->port_mode[0])) | 286 | for (i = 0; i < omap->nports; i++) { |
298 | clk_enable(omap->usbhost_p1_fck); | 287 | switch (pdata->port_mode[i]) { |
299 | if (is_ehci_tll_mode(pdata->port_mode[1])) | 288 | case OMAP_EHCI_PORT_MODE_HSIC: |
300 | clk_enable(omap->usbhost_p2_fck); | 289 | if (!IS_ERR(omap->hsic60m_clk[i])) { |
301 | 290 | r = clk_enable(omap->hsic60m_clk[i]); | |
302 | clk_enable(omap->utmi_p1_fck); | 291 | if (r) { |
303 | clk_enable(omap->utmi_p2_fck); | 292 | dev_err(dev, |
293 | "Can't enable port %d hsic60m clk:%d\n", | ||
294 | i, r); | ||
295 | } | ||
296 | } | ||
304 | 297 | ||
305 | spin_unlock_irqrestore(&omap->lock, flags); | 298 | if (!IS_ERR(omap->hsic480m_clk[i])) { |
299 | r = clk_enable(omap->hsic480m_clk[i]); | ||
300 | if (r) { | ||
301 | dev_err(dev, | ||
302 | "Can't enable port %d hsic480m clk:%d\n", | ||
303 | i, r); | ||
304 | } | ||
305 | } | ||
306 | /* Fall through as HSIC mode needs utmi_clk */ | ||
307 | |||
308 | case OMAP_EHCI_PORT_MODE_TLL: | ||
309 | if (!IS_ERR(omap->utmi_clk[i])) { | ||
310 | r = clk_enable(omap->utmi_clk[i]); | ||
311 | if (r) { | ||
312 | dev_err(dev, | ||
313 | "Can't enable port %d clk : %d\n", | ||
314 | i, r); | ||
315 | } | ||
316 | } | ||
317 | break; | ||
318 | default: | ||
319 | break; | ||
320 | } | ||
321 | } | ||
306 | 322 | ||
307 | return 0; | 323 | return 0; |
308 | } | 324 | } |
@@ -310,51 +326,122 @@ static int usbhs_runtime_resume(struct device *dev) | |||
310 | static int usbhs_runtime_suspend(struct device *dev) | 326 | static int usbhs_runtime_suspend(struct device *dev) |
311 | { | 327 | { |
312 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | 328 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); |
313 | struct usbhs_omap_platform_data *pdata = &omap->platdata; | 329 | struct usbhs_omap_platform_data *pdata = omap->pdata; |
314 | unsigned long flags; | 330 | int i; |
315 | 331 | ||
316 | dev_dbg(dev, "usbhs_runtime_suspend\n"); | 332 | dev_dbg(dev, "usbhs_runtime_suspend\n"); |
317 | 333 | ||
318 | if (!pdata) { | 334 | for (i = 0; i < omap->nports; i++) { |
319 | dev_dbg(dev, "missing platform_data\n"); | 335 | switch (pdata->port_mode[i]) { |
320 | return -ENODEV; | 336 | case OMAP_EHCI_PORT_MODE_HSIC: |
321 | } | 337 | if (!IS_ERR(omap->hsic60m_clk[i])) |
322 | 338 | clk_disable(omap->hsic60m_clk[i]); | |
323 | spin_lock_irqsave(&omap->lock, flags); | ||
324 | 339 | ||
325 | if (is_ehci_tll_mode(pdata->port_mode[0])) | 340 | if (!IS_ERR(omap->hsic480m_clk[i])) |
326 | clk_disable(omap->usbhost_p1_fck); | 341 | clk_disable(omap->hsic480m_clk[i]); |
327 | if (is_ehci_tll_mode(pdata->port_mode[1])) | 342 | /* Fall through as utmi_clks were used in HSIC mode */ |
328 | clk_disable(omap->usbhost_p2_fck); | ||
329 | 343 | ||
330 | clk_disable(omap->utmi_p2_fck); | 344 | case OMAP_EHCI_PORT_MODE_TLL: |
331 | clk_disable(omap->utmi_p1_fck); | 345 | if (!IS_ERR(omap->utmi_clk[i])) |
346 | clk_disable(omap->utmi_clk[i]); | ||
347 | break; | ||
348 | default: | ||
349 | break; | ||
350 | } | ||
351 | } | ||
332 | 352 | ||
333 | if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) | 353 | if (!IS_ERR(omap->ehci_logic_fck)) |
334 | clk_disable(omap->ehci_logic_fck); | 354 | clk_disable(omap->ehci_logic_fck); |
335 | 355 | ||
336 | spin_unlock_irqrestore(&omap->lock, flags); | ||
337 | omap_tll_disable(); | 356 | omap_tll_disable(); |
338 | 357 | ||
339 | return 0; | 358 | return 0; |
340 | } | 359 | } |
341 | 360 | ||
361 | static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap, | ||
362 | unsigned reg) | ||
363 | { | ||
364 | struct usbhs_omap_platform_data *pdata = omap->pdata; | ||
365 | int i; | ||
366 | |||
367 | for (i = 0; i < omap->nports; i++) { | ||
368 | switch (pdata->port_mode[i]) { | ||
369 | case OMAP_USBHS_PORT_MODE_UNUSED: | ||
370 | reg &= ~(OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS << i); | ||
371 | break; | ||
372 | case OMAP_EHCI_PORT_MODE_PHY: | ||
373 | if (pdata->single_ulpi_bypass) | ||
374 | break; | ||
375 | |||
376 | if (i == 0) | ||
377 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
378 | else | ||
379 | reg &= ~(OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS | ||
380 | << (i-1)); | ||
381 | break; | ||
382 | default: | ||
383 | if (pdata->single_ulpi_bypass) | ||
384 | break; | ||
385 | |||
386 | if (i == 0) | ||
387 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
388 | else | ||
389 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS | ||
390 | << (i-1); | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (pdata->single_ulpi_bypass) { | ||
396 | /* bypass ULPI only if none of the ports use PHY mode */ | ||
397 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | ||
398 | |||
399 | for (i = 0; i < omap->nports; i++) { | ||
400 | if (is_ehci_phy_mode(pdata->port_mode[i])) { | ||
401 | reg &= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | ||
402 | break; | ||
403 | } | ||
404 | } | ||
405 | } | ||
406 | |||
407 | return reg; | ||
408 | } | ||
409 | |||
410 | static unsigned omap_usbhs_rev2_hostconfig(struct usbhs_hcd_omap *omap, | ||
411 | unsigned reg) | ||
412 | { | ||
413 | struct usbhs_omap_platform_data *pdata = omap->pdata; | ||
414 | int i; | ||
415 | |||
416 | for (i = 0; i < omap->nports; i++) { | ||
417 | /* Clear port mode fields for PHY mode */ | ||
418 | reg &= ~(OMAP4_P1_MODE_CLEAR << 2 * i); | ||
419 | |||
420 | if (is_ehci_tll_mode(pdata->port_mode[i]) || | ||
421 | (is_ohci_port(pdata->port_mode[i]))) | ||
422 | reg |= OMAP4_P1_MODE_TLL << 2 * i; | ||
423 | else if (is_ehci_hsic_mode(pdata->port_mode[i])) | ||
424 | reg |= OMAP4_P1_MODE_HSIC << 2 * i; | ||
425 | } | ||
426 | |||
427 | return reg; | ||
428 | } | ||
429 | |||
342 | static void omap_usbhs_init(struct device *dev) | 430 | static void omap_usbhs_init(struct device *dev) |
343 | { | 431 | { |
344 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | 432 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); |
345 | struct usbhs_omap_platform_data *pdata = &omap->platdata; | 433 | struct usbhs_omap_platform_data *pdata = omap->pdata; |
346 | unsigned long flags; | ||
347 | unsigned reg; | 434 | unsigned reg; |
348 | 435 | ||
349 | dev_dbg(dev, "starting TI HSUSB Controller\n"); | 436 | dev_dbg(dev, "starting TI HSUSB Controller\n"); |
350 | 437 | ||
351 | if (pdata->ehci_data->phy_reset) { | 438 | if (pdata->phy_reset) { |
352 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | 439 | if (gpio_is_valid(pdata->reset_gpio_port[0])) |
353 | gpio_request_one(pdata->ehci_data->reset_gpio_port[0], | 440 | gpio_request_one(pdata->reset_gpio_port[0], |
354 | GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); | 441 | GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); |
355 | 442 | ||
356 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | 443 | if (gpio_is_valid(pdata->reset_gpio_port[1])) |
357 | gpio_request_one(pdata->ehci_data->reset_gpio_port[1], | 444 | gpio_request_one(pdata->reset_gpio_port[1], |
358 | GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); | 445 | GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); |
359 | 446 | ||
360 | /* Hold the PHY in RESET for enough time till DIR is high */ | 447 | /* Hold the PHY in RESET for enough time till DIR is high */ |
@@ -362,9 +449,6 @@ static void omap_usbhs_init(struct device *dev) | |||
362 | } | 449 | } |
363 | 450 | ||
364 | pm_runtime_get_sync(dev); | 451 | pm_runtime_get_sync(dev); |
365 | spin_lock_irqsave(&omap->lock, flags); | ||
366 | omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); | ||
367 | dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); | ||
368 | 452 | ||
369 | reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); | 453 | reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); |
370 | /* setup ULPI bypass and burst configurations */ | 454 | /* setup ULPI bypass and burst configurations */ |
@@ -374,89 +458,51 @@ static void omap_usbhs_init(struct device *dev) | |||
374 | reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK; | 458 | reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK; |
375 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; | 459 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; |
376 | 460 | ||
377 | if (is_omap_usbhs_rev1(omap)) { | 461 | switch (omap->usbhs_rev) { |
378 | if (pdata->port_mode[0] == OMAP_USBHS_PORT_MODE_UNUSED) | 462 | case OMAP_USBHS_REV1: |
379 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; | 463 | omap_usbhs_rev1_hostconfig(omap, reg); |
380 | if (pdata->port_mode[1] == OMAP_USBHS_PORT_MODE_UNUSED) | 464 | break; |
381 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; | ||
382 | if (pdata->port_mode[2] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
383 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | ||
384 | |||
385 | /* Bypass the TLL module for PHY mode operation */ | ||
386 | if (pdata->single_ulpi_bypass) { | ||
387 | dev_dbg(dev, "OMAP3 ES version <= ES2.1\n"); | ||
388 | if (is_ehci_phy_mode(pdata->port_mode[0]) || | ||
389 | is_ehci_phy_mode(pdata->port_mode[1]) || | ||
390 | is_ehci_phy_mode(pdata->port_mode[2])) | ||
391 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | ||
392 | else | ||
393 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | ||
394 | } else { | ||
395 | dev_dbg(dev, "OMAP3 ES version > ES2.1\n"); | ||
396 | if (is_ehci_phy_mode(pdata->port_mode[0])) | ||
397 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
398 | else | ||
399 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
400 | if (is_ehci_phy_mode(pdata->port_mode[1])) | ||
401 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | ||
402 | else | ||
403 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | ||
404 | if (is_ehci_phy_mode(pdata->port_mode[2])) | ||
405 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
406 | else | ||
407 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
408 | } | ||
409 | } else if (is_omap_usbhs_rev2(omap)) { | ||
410 | /* Clear port mode fields for PHY mode*/ | ||
411 | reg &= ~OMAP4_P1_MODE_CLEAR; | ||
412 | reg &= ~OMAP4_P2_MODE_CLEAR; | ||
413 | 465 | ||
414 | if (is_ehci_tll_mode(pdata->port_mode[0]) || | 466 | case OMAP_USBHS_REV2: |
415 | (is_ohci_port(pdata->port_mode[0]))) | 467 | omap_usbhs_rev2_hostconfig(omap, reg); |
416 | reg |= OMAP4_P1_MODE_TLL; | 468 | break; |
417 | else if (is_ehci_hsic_mode(pdata->port_mode[0])) | ||
418 | reg |= OMAP4_P1_MODE_HSIC; | ||
419 | 469 | ||
420 | if (is_ehci_tll_mode(pdata->port_mode[1]) || | 470 | default: /* newer revisions */ |
421 | (is_ohci_port(pdata->port_mode[1]))) | 471 | omap_usbhs_rev2_hostconfig(omap, reg); |
422 | reg |= OMAP4_P2_MODE_TLL; | 472 | break; |
423 | else if (is_ehci_hsic_mode(pdata->port_mode[1])) | ||
424 | reg |= OMAP4_P2_MODE_HSIC; | ||
425 | } | 473 | } |
426 | 474 | ||
427 | usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); | 475 | usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); |
428 | dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg); | 476 | dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg); |
429 | 477 | ||
430 | spin_unlock_irqrestore(&omap->lock, flags); | ||
431 | |||
432 | pm_runtime_put_sync(dev); | 478 | pm_runtime_put_sync(dev); |
433 | if (pdata->ehci_data->phy_reset) { | 479 | if (pdata->phy_reset) { |
434 | /* Hold the PHY in RESET for enough time till | 480 | /* Hold the PHY in RESET for enough time till |
435 | * PHY is settled and ready | 481 | * PHY is settled and ready |
436 | */ | 482 | */ |
437 | udelay(10); | 483 | udelay(10); |
438 | 484 | ||
439 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | 485 | if (gpio_is_valid(pdata->reset_gpio_port[0])) |
440 | gpio_set_value_cansleep | 486 | gpio_set_value_cansleep |
441 | (pdata->ehci_data->reset_gpio_port[0], 1); | 487 | (pdata->reset_gpio_port[0], 1); |
442 | 488 | ||
443 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | 489 | if (gpio_is_valid(pdata->reset_gpio_port[1])) |
444 | gpio_set_value_cansleep | 490 | gpio_set_value_cansleep |
445 | (pdata->ehci_data->reset_gpio_port[1], 1); | 491 | (pdata->reset_gpio_port[1], 1); |
446 | } | 492 | } |
447 | } | 493 | } |
448 | 494 | ||
449 | static void omap_usbhs_deinit(struct device *dev) | 495 | static void omap_usbhs_deinit(struct device *dev) |
450 | { | 496 | { |
451 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); | 497 | struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); |
452 | struct usbhs_omap_platform_data *pdata = &omap->platdata; | 498 | struct usbhs_omap_platform_data *pdata = omap->pdata; |
453 | 499 | ||
454 | if (pdata->ehci_data->phy_reset) { | 500 | if (pdata->phy_reset) { |
455 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) | 501 | if (gpio_is_valid(pdata->reset_gpio_port[0])) |
456 | gpio_free(pdata->ehci_data->reset_gpio_port[0]); | 502 | gpio_free(pdata->reset_gpio_port[0]); |
457 | 503 | ||
458 | if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) | 504 | if (gpio_is_valid(pdata->reset_gpio_port[1])) |
459 | gpio_free(pdata->ehci_data->reset_gpio_port[1]); | 505 | gpio_free(pdata->reset_gpio_port[1]); |
460 | } | 506 | } |
461 | } | 507 | } |
462 | 508 | ||
@@ -474,137 +520,185 @@ static int usbhs_omap_probe(struct platform_device *pdev) | |||
474 | struct resource *res; | 520 | struct resource *res; |
475 | int ret = 0; | 521 | int ret = 0; |
476 | int i; | 522 | int i; |
523 | bool need_logic_fck; | ||
477 | 524 | ||
478 | if (!pdata) { | 525 | if (!pdata) { |
479 | dev_err(dev, "Missing platform data\n"); | 526 | dev_err(dev, "Missing platform data\n"); |
480 | ret = -ENOMEM; | 527 | return -ENODEV; |
481 | goto end_probe; | ||
482 | } | 528 | } |
483 | 529 | ||
484 | omap = kzalloc(sizeof(*omap), GFP_KERNEL); | 530 | omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL); |
485 | if (!omap) { | 531 | if (!omap) { |
486 | dev_err(dev, "Memory allocation failed\n"); | 532 | dev_err(dev, "Memory allocation failed\n"); |
487 | ret = -ENOMEM; | 533 | return -ENOMEM; |
488 | goto end_probe; | ||
489 | } | 534 | } |
490 | 535 | ||
491 | spin_lock_init(&omap->lock); | 536 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); |
492 | 537 | omap->uhh_base = devm_request_and_ioremap(dev, res); | |
493 | for (i = 0; i < OMAP3_HS_USB_PORTS; i++) | 538 | if (!omap->uhh_base) { |
494 | omap->platdata.port_mode[i] = pdata->port_mode[i]; | 539 | dev_err(dev, "Resource request/ioremap failed\n"); |
540 | return -EADDRNOTAVAIL; | ||
541 | } | ||
495 | 542 | ||
496 | omap->platdata.ehci_data = pdata->ehci_data; | 543 | omap->pdata = pdata; |
497 | omap->platdata.ohci_data = pdata->ohci_data; | ||
498 | 544 | ||
499 | pm_runtime_enable(dev); | 545 | pm_runtime_enable(dev); |
500 | 546 | ||
547 | platform_set_drvdata(pdev, omap); | ||
548 | pm_runtime_get_sync(dev); | ||
549 | |||
550 | omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); | ||
501 | 551 | ||
502 | for (i = 0; i < OMAP3_HS_USB_PORTS; i++) | 552 | /* we need to call runtime suspend before we update omap->nports |
503 | if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || | 553 | * to prevent unbalanced clk_disable() |
504 | is_ehci_hsic_mode(i)) { | 554 | */ |
505 | omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); | 555 | pm_runtime_put_sync(dev); |
506 | if (IS_ERR(omap->ehci_logic_fck)) { | 556 | |
507 | ret = PTR_ERR(omap->ehci_logic_fck); | 557 | /* |
508 | dev_warn(dev, "ehci_logic_fck failed:%d\n", | 558 | * If platform data contains nports then use that |
509 | ret); | 559 | * else make out number of ports from USBHS revision |
510 | } | 560 | */ |
561 | if (pdata->nports) { | ||
562 | omap->nports = pdata->nports; | ||
563 | } else { | ||
564 | switch (omap->usbhs_rev) { | ||
565 | case OMAP_USBHS_REV1: | ||
566 | omap->nports = 3; | ||
567 | break; | ||
568 | case OMAP_USBHS_REV2: | ||
569 | omap->nports = 2; | ||
570 | break; | ||
571 | default: | ||
572 | omap->nports = OMAP3_HS_USB_PORTS; | ||
573 | dev_dbg(dev, | ||
574 | "USB HOST Rev:0x%d not recognized, assuming %d ports\n", | ||
575 | omap->usbhs_rev, omap->nports); | ||
511 | break; | 576 | break; |
512 | } | 577 | } |
578 | } | ||
513 | 579 | ||
514 | omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); | 580 | i = sizeof(struct clk *) * omap->nports; |
515 | if (IS_ERR(omap->utmi_p1_fck)) { | 581 | omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL); |
516 | ret = PTR_ERR(omap->utmi_p1_fck); | 582 | omap->hsic480m_clk = devm_kzalloc(dev, i, GFP_KERNEL); |
517 | dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); | 583 | omap->hsic60m_clk = devm_kzalloc(dev, i, GFP_KERNEL); |
518 | goto err_end; | 584 | |
585 | if (!omap->utmi_clk || !omap->hsic480m_clk || !omap->hsic60m_clk) { | ||
586 | dev_err(dev, "Memory allocation failed\n"); | ||
587 | ret = -ENOMEM; | ||
588 | goto err_mem; | ||
589 | } | ||
590 | |||
591 | need_logic_fck = false; | ||
592 | for (i = 0; i < omap->nports; i++) { | ||
593 | if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || | ||
594 | is_ehci_hsic_mode(i)) | ||
595 | need_logic_fck |= true; | ||
596 | } | ||
597 | |||
598 | omap->ehci_logic_fck = ERR_PTR(-EINVAL); | ||
599 | if (need_logic_fck) { | ||
600 | omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); | ||
601 | if (IS_ERR(omap->ehci_logic_fck)) { | ||
602 | ret = PTR_ERR(omap->ehci_logic_fck); | ||
603 | dev_dbg(dev, "ehci_logic_fck failed:%d\n", ret); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | omap->utmi_p1_gfclk = clk_get(dev, "utmi_p1_gfclk"); | ||
608 | if (IS_ERR(omap->utmi_p1_gfclk)) { | ||
609 | ret = PTR_ERR(omap->utmi_p1_gfclk); | ||
610 | dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); | ||
611 | goto err_p1_gfclk; | ||
612 | } | ||
613 | |||
614 | omap->utmi_p2_gfclk = clk_get(dev, "utmi_p2_gfclk"); | ||
615 | if (IS_ERR(omap->utmi_p2_gfclk)) { | ||
616 | ret = PTR_ERR(omap->utmi_p2_gfclk); | ||
617 | dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); | ||
618 | goto err_p2_gfclk; | ||
519 | } | 619 | } |
520 | 620 | ||
521 | omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); | 621 | omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); |
522 | if (IS_ERR(omap->xclk60mhsp1_ck)) { | 622 | if (IS_ERR(omap->xclk60mhsp1_ck)) { |
523 | ret = PTR_ERR(omap->xclk60mhsp1_ck); | 623 | ret = PTR_ERR(omap->xclk60mhsp1_ck); |
524 | dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); | 624 | dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); |
525 | goto err_utmi_p1_fck; | 625 | goto err_xclk60mhsp1; |
526 | } | ||
527 | |||
528 | omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); | ||
529 | if (IS_ERR(omap->utmi_p2_fck)) { | ||
530 | ret = PTR_ERR(omap->utmi_p2_fck); | ||
531 | dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); | ||
532 | goto err_xclk60mhsp1_ck; | ||
533 | } | 626 | } |
534 | 627 | ||
535 | omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); | 628 | omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); |
536 | if (IS_ERR(omap->xclk60mhsp2_ck)) { | 629 | if (IS_ERR(omap->xclk60mhsp2_ck)) { |
537 | ret = PTR_ERR(omap->xclk60mhsp2_ck); | 630 | ret = PTR_ERR(omap->xclk60mhsp2_ck); |
538 | dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); | 631 | dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); |
539 | goto err_utmi_p2_fck; | 632 | goto err_xclk60mhsp2; |
540 | } | ||
541 | |||
542 | omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); | ||
543 | if (IS_ERR(omap->usbhost_p1_fck)) { | ||
544 | ret = PTR_ERR(omap->usbhost_p1_fck); | ||
545 | dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); | ||
546 | goto err_xclk60mhsp2_ck; | ||
547 | } | ||
548 | |||
549 | omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); | ||
550 | if (IS_ERR(omap->usbhost_p2_fck)) { | ||
551 | ret = PTR_ERR(omap->usbhost_p2_fck); | ||
552 | dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); | ||
553 | goto err_usbhost_p1_fck; | ||
554 | } | 633 | } |
555 | 634 | ||
556 | omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); | 635 | omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); |
557 | if (IS_ERR(omap->init_60m_fclk)) { | 636 | if (IS_ERR(omap->init_60m_fclk)) { |
558 | ret = PTR_ERR(omap->init_60m_fclk); | 637 | ret = PTR_ERR(omap->init_60m_fclk); |
559 | dev_err(dev, "init_60m_fclk failed error:%d\n", ret); | 638 | dev_err(dev, "init_60m_fclk failed error:%d\n", ret); |
560 | goto err_usbhost_p2_fck; | 639 | goto err_init60m; |
640 | } | ||
641 | |||
642 | for (i = 0; i < omap->nports; i++) { | ||
643 | char clkname[30]; | ||
644 | |||
645 | /* clock names are indexed from 1*/ | ||
646 | snprintf(clkname, sizeof(clkname), | ||
647 | "usb_host_hs_utmi_p%d_clk", i + 1); | ||
648 | |||
649 | /* If a clock is not found we won't bail out as not all | ||
650 | * platforms have all clocks and we can function without | ||
651 | * them | ||
652 | */ | ||
653 | omap->utmi_clk[i] = clk_get(dev, clkname); | ||
654 | if (IS_ERR(omap->utmi_clk[i])) | ||
655 | dev_dbg(dev, "Failed to get clock : %s : %ld\n", | ||
656 | clkname, PTR_ERR(omap->utmi_clk[i])); | ||
657 | |||
658 | snprintf(clkname, sizeof(clkname), | ||
659 | "usb_host_hs_hsic480m_p%d_clk", i + 1); | ||
660 | omap->hsic480m_clk[i] = clk_get(dev, clkname); | ||
661 | if (IS_ERR(omap->hsic480m_clk[i])) | ||
662 | dev_dbg(dev, "Failed to get clock : %s : %ld\n", | ||
663 | clkname, PTR_ERR(omap->hsic480m_clk[i])); | ||
664 | |||
665 | snprintf(clkname, sizeof(clkname), | ||
666 | "usb_host_hs_hsic60m_p%d_clk", i + 1); | ||
667 | omap->hsic60m_clk[i] = clk_get(dev, clkname); | ||
668 | if (IS_ERR(omap->hsic60m_clk[i])) | ||
669 | dev_dbg(dev, "Failed to get clock : %s : %ld\n", | ||
670 | clkname, PTR_ERR(omap->hsic60m_clk[i])); | ||
561 | } | 671 | } |
562 | 672 | ||
563 | if (is_ehci_phy_mode(pdata->port_mode[0])) { | 673 | if (is_ehci_phy_mode(pdata->port_mode[0])) { |
564 | /* for OMAP3 , the clk set paretn fails */ | 674 | /* for OMAP3, clk_set_parent fails */ |
565 | ret = clk_set_parent(omap->utmi_p1_fck, | 675 | ret = clk_set_parent(omap->utmi_p1_gfclk, |
566 | omap->xclk60mhsp1_ck); | 676 | omap->xclk60mhsp1_ck); |
567 | if (ret != 0) | 677 | if (ret != 0) |
568 | dev_err(dev, "xclk60mhsp1_ck set parent" | 678 | dev_dbg(dev, "xclk60mhsp1_ck set parent failed: %d\n", |
569 | "failed error:%d\n", ret); | 679 | ret); |
570 | } else if (is_ehci_tll_mode(pdata->port_mode[0])) { | 680 | } else if (is_ehci_tll_mode(pdata->port_mode[0])) { |
571 | ret = clk_set_parent(omap->utmi_p1_fck, | 681 | ret = clk_set_parent(omap->utmi_p1_gfclk, |
572 | omap->init_60m_fclk); | 682 | omap->init_60m_fclk); |
573 | if (ret != 0) | 683 | if (ret != 0) |
574 | dev_err(dev, "init_60m_fclk set parent" | 684 | dev_dbg(dev, "P0 init_60m_fclk set parent failed: %d\n", |
575 | "failed error:%d\n", ret); | 685 | ret); |
576 | } | 686 | } |
577 | 687 | ||
578 | if (is_ehci_phy_mode(pdata->port_mode[1])) { | 688 | if (is_ehci_phy_mode(pdata->port_mode[1])) { |
579 | ret = clk_set_parent(omap->utmi_p2_fck, | 689 | ret = clk_set_parent(omap->utmi_p2_gfclk, |
580 | omap->xclk60mhsp2_ck); | 690 | omap->xclk60mhsp2_ck); |
581 | if (ret != 0) | 691 | if (ret != 0) |
582 | dev_err(dev, "xclk60mhsp2_ck set parent" | 692 | dev_dbg(dev, "xclk60mhsp2_ck set parent failed: %d\n", |
583 | "failed error:%d\n", ret); | 693 | ret); |
584 | } else if (is_ehci_tll_mode(pdata->port_mode[1])) { | 694 | } else if (is_ehci_tll_mode(pdata->port_mode[1])) { |
585 | ret = clk_set_parent(omap->utmi_p2_fck, | 695 | ret = clk_set_parent(omap->utmi_p2_gfclk, |
586 | omap->init_60m_fclk); | 696 | omap->init_60m_fclk); |
587 | if (ret != 0) | 697 | if (ret != 0) |
588 | dev_err(dev, "init_60m_fclk set parent" | 698 | dev_dbg(dev, "P1 init_60m_fclk set parent failed: %d\n", |
589 | "failed error:%d\n", ret); | 699 | ret); |
590 | } | ||
591 | |||
592 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); | ||
593 | if (!res) { | ||
594 | dev_err(dev, "UHH EHCI get resource failed\n"); | ||
595 | ret = -ENODEV; | ||
596 | goto err_init_60m_fclk; | ||
597 | } | ||
598 | |||
599 | omap->uhh_base = ioremap(res->start, resource_size(res)); | ||
600 | if (!omap->uhh_base) { | ||
601 | dev_err(dev, "UHH ioremap failed\n"); | ||
602 | ret = -ENOMEM; | ||
603 | goto err_init_60m_fclk; | ||
604 | } | 700 | } |
605 | 701 | ||
606 | platform_set_drvdata(pdev, omap); | ||
607 | |||
608 | omap_usbhs_init(dev); | 702 | omap_usbhs_init(dev); |
609 | ret = omap_usbhs_alloc_children(pdev); | 703 | ret = omap_usbhs_alloc_children(pdev); |
610 | if (ret) { | 704 | if (ret) { |
@@ -612,39 +706,41 @@ static int usbhs_omap_probe(struct platform_device *pdev) | |||
612 | goto err_alloc; | 706 | goto err_alloc; |
613 | } | 707 | } |
614 | 708 | ||
615 | goto end_probe; | 709 | return 0; |
616 | 710 | ||
617 | err_alloc: | 711 | err_alloc: |
618 | omap_usbhs_deinit(&pdev->dev); | 712 | omap_usbhs_deinit(&pdev->dev); |
619 | iounmap(omap->uhh_base); | ||
620 | |||
621 | err_init_60m_fclk: | ||
622 | clk_put(omap->init_60m_fclk); | ||
623 | 713 | ||
624 | err_usbhost_p2_fck: | 714 | for (i = 0; i < omap->nports; i++) { |
625 | clk_put(omap->usbhost_p2_fck); | 715 | if (!IS_ERR(omap->utmi_clk[i])) |
716 | clk_put(omap->utmi_clk[i]); | ||
717 | if (!IS_ERR(omap->hsic60m_clk[i])) | ||
718 | clk_put(omap->hsic60m_clk[i]); | ||
719 | if (!IS_ERR(omap->hsic480m_clk[i])) | ||
720 | clk_put(omap->hsic480m_clk[i]); | ||
721 | } | ||
626 | 722 | ||
627 | err_usbhost_p1_fck: | 723 | clk_put(omap->init_60m_fclk); |
628 | clk_put(omap->usbhost_p1_fck); | ||
629 | 724 | ||
630 | err_xclk60mhsp2_ck: | 725 | err_init60m: |
631 | clk_put(omap->xclk60mhsp2_ck); | 726 | clk_put(omap->xclk60mhsp2_ck); |
632 | 727 | ||
633 | err_utmi_p2_fck: | 728 | err_xclk60mhsp2: |
634 | clk_put(omap->utmi_p2_fck); | ||
635 | |||
636 | err_xclk60mhsp1_ck: | ||
637 | clk_put(omap->xclk60mhsp1_ck); | 729 | clk_put(omap->xclk60mhsp1_ck); |
638 | 730 | ||
639 | err_utmi_p1_fck: | 731 | err_xclk60mhsp1: |
640 | clk_put(omap->utmi_p1_fck); | 732 | clk_put(omap->utmi_p2_gfclk); |
641 | 733 | ||
642 | err_end: | 734 | err_p2_gfclk: |
643 | clk_put(omap->ehci_logic_fck); | 735 | clk_put(omap->utmi_p1_gfclk); |
736 | |||
737 | err_p1_gfclk: | ||
738 | if (!IS_ERR(omap->ehci_logic_fck)) | ||
739 | clk_put(omap->ehci_logic_fck); | ||
740 | |||
741 | err_mem: | ||
644 | pm_runtime_disable(dev); | 742 | pm_runtime_disable(dev); |
645 | kfree(omap); | ||
646 | 743 | ||
647 | end_probe: | ||
648 | return ret; | 744 | return ret; |
649 | } | 745 | } |
650 | 746 | ||
@@ -657,19 +753,29 @@ end_probe: | |||
657 | static int usbhs_omap_remove(struct platform_device *pdev) | 753 | static int usbhs_omap_remove(struct platform_device *pdev) |
658 | { | 754 | { |
659 | struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); | 755 | struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); |
756 | int i; | ||
660 | 757 | ||
661 | omap_usbhs_deinit(&pdev->dev); | 758 | omap_usbhs_deinit(&pdev->dev); |
662 | iounmap(omap->uhh_base); | 759 | |
760 | for (i = 0; i < omap->nports; i++) { | ||
761 | if (!IS_ERR(omap->utmi_clk[i])) | ||
762 | clk_put(omap->utmi_clk[i]); | ||
763 | if (!IS_ERR(omap->hsic60m_clk[i])) | ||
764 | clk_put(omap->hsic60m_clk[i]); | ||
765 | if (!IS_ERR(omap->hsic480m_clk[i])) | ||
766 | clk_put(omap->hsic480m_clk[i]); | ||
767 | } | ||
768 | |||
663 | clk_put(omap->init_60m_fclk); | 769 | clk_put(omap->init_60m_fclk); |
664 | clk_put(omap->usbhost_p2_fck); | 770 | clk_put(omap->utmi_p1_gfclk); |
665 | clk_put(omap->usbhost_p1_fck); | 771 | clk_put(omap->utmi_p2_gfclk); |
666 | clk_put(omap->xclk60mhsp2_ck); | 772 | clk_put(omap->xclk60mhsp2_ck); |
667 | clk_put(omap->utmi_p2_fck); | ||
668 | clk_put(omap->xclk60mhsp1_ck); | 773 | clk_put(omap->xclk60mhsp1_ck); |
669 | clk_put(omap->utmi_p1_fck); | 774 | |
670 | clk_put(omap->ehci_logic_fck); | 775 | if (!IS_ERR(omap->ehci_logic_fck)) |
776 | clk_put(omap->ehci_logic_fck); | ||
777 | |||
671 | pm_runtime_disable(&pdev->dev); | 778 | pm_runtime_disable(&pdev->dev); |
672 | kfree(omap); | ||
673 | 779 | ||
674 | return 0; | 780 | return 0; |
675 | } | 781 | } |
@@ -685,7 +791,7 @@ static struct platform_driver usbhs_omap_driver = { | |||
685 | .owner = THIS_MODULE, | 791 | .owner = THIS_MODULE, |
686 | .pm = &usbhsomap_dev_pm_ops, | 792 | .pm = &usbhsomap_dev_pm_ops, |
687 | }, | 793 | }, |
688 | .remove = __exit_p(usbhs_omap_remove), | 794 | .remove = usbhs_omap_remove, |
689 | }; | 795 | }; |
690 | 796 | ||
691 | MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>"); | 797 | MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>"); |
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index eb869153206d..0aef1a768880 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c | |||
@@ -54,10 +54,13 @@ | |||
54 | 54 | ||
55 | #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) | 55 | #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) |
56 | #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24 | 56 | #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24 |
57 | #define OMAP_TLL_CHANNEL_CONF_DRVVBUS (1 << 16) | ||
58 | #define OMAP_TLL_CHANNEL_CONF_CHRGVBUS (1 << 15) | ||
57 | #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) | 59 | #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) |
58 | #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) | 60 | #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) |
59 | #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) | 61 | #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) |
60 | #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) | 62 | #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) |
63 | #define OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI (2 << 1) | ||
61 | #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1) | 64 | #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1) |
62 | #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) | 65 | #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) |
63 | 66 | ||
@@ -92,21 +95,25 @@ | |||
92 | #define OMAP_USBTLL_REV1 0x00000015 /* OMAP3 */ | 95 | #define OMAP_USBTLL_REV1 0x00000015 /* OMAP3 */ |
93 | #define OMAP_USBTLL_REV2 0x00000018 /* OMAP 3630 */ | 96 | #define OMAP_USBTLL_REV2 0x00000018 /* OMAP 3630 */ |
94 | #define OMAP_USBTLL_REV3 0x00000004 /* OMAP4 */ | 97 | #define OMAP_USBTLL_REV3 0x00000004 /* OMAP4 */ |
98 | #define OMAP_USBTLL_REV4 0x00000006 /* OMAP5 */ | ||
95 | 99 | ||
96 | #define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL) | 100 | #define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL) |
97 | 101 | ||
102 | /* only PHY and UNUSED modes don't need TLL */ | ||
103 | #define omap_usb_mode_needs_tll(x) ((x) != OMAP_USBHS_PORT_MODE_UNUSED &&\ | ||
104 | (x) != OMAP_EHCI_PORT_MODE_PHY) | ||
105 | |||
98 | struct usbtll_omap { | 106 | struct usbtll_omap { |
99 | struct clk *usbtll_p1_fck; | 107 | int nch; /* num. of channels */ |
100 | struct clk *usbtll_p2_fck; | 108 | struct usbhs_omap_platform_data *pdata; |
101 | struct usbtll_omap_platform_data platdata; | 109 | struct clk **ch_clk; |
102 | /* secure the register updates */ | ||
103 | spinlock_t lock; | ||
104 | }; | 110 | }; |
105 | 111 | ||
106 | /*-------------------------------------------------------------------------*/ | 112 | /*-------------------------------------------------------------------------*/ |
107 | 113 | ||
108 | const char usbtll_driver_name[] = USBTLL_DRIVER_NAME; | 114 | static const char usbtll_driver_name[] = USBTLL_DRIVER_NAME; |
109 | struct platform_device *tll_pdev; | 115 | static struct device *tll_dev; |
116 | static DEFINE_SPINLOCK(tll_lock); /* serialize access to tll_dev */ | ||
110 | 117 | ||
111 | /*-------------------------------------------------------------------------*/ | 118 | /*-------------------------------------------------------------------------*/ |
112 | 119 | ||
@@ -203,84 +210,84 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) | |||
203 | static int usbtll_omap_probe(struct platform_device *pdev) | 210 | static int usbtll_omap_probe(struct platform_device *pdev) |
204 | { | 211 | { |
205 | struct device *dev = &pdev->dev; | 212 | struct device *dev = &pdev->dev; |
206 | struct usbtll_omap_platform_data *pdata = dev->platform_data; | 213 | struct usbhs_omap_platform_data *pdata = dev->platform_data; |
207 | void __iomem *base; | 214 | void __iomem *base; |
208 | struct resource *res; | 215 | struct resource *res; |
209 | struct usbtll_omap *tll; | 216 | struct usbtll_omap *tll; |
210 | unsigned reg; | 217 | unsigned reg; |
211 | unsigned long flags; | ||
212 | int ret = 0; | 218 | int ret = 0; |
213 | int i, ver, count; | 219 | int i, ver; |
220 | bool needs_tll; | ||
214 | 221 | ||
215 | dev_dbg(dev, "starting TI HSUSB TLL Controller\n"); | 222 | dev_dbg(dev, "starting TI HSUSB TLL Controller\n"); |
216 | 223 | ||
217 | tll = kzalloc(sizeof(struct usbtll_omap), GFP_KERNEL); | 224 | tll = devm_kzalloc(dev, sizeof(struct usbtll_omap), GFP_KERNEL); |
218 | if (!tll) { | 225 | if (!tll) { |
219 | dev_err(dev, "Memory allocation failed\n"); | 226 | dev_err(dev, "Memory allocation failed\n"); |
220 | ret = -ENOMEM; | 227 | return -ENOMEM; |
221 | goto end; | ||
222 | } | 228 | } |
223 | 229 | ||
224 | spin_lock_init(&tll->lock); | 230 | if (!pdata) { |
225 | 231 | dev_err(dev, "Platform data missing\n"); | |
226 | for (i = 0; i < OMAP3_HS_USB_PORTS; i++) | 232 | return -ENODEV; |
227 | tll->platdata.port_mode[i] = pdata->port_mode[i]; | ||
228 | |||
229 | tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); | ||
230 | if (IS_ERR(tll->usbtll_p1_fck)) { | ||
231 | ret = PTR_ERR(tll->usbtll_p1_fck); | ||
232 | dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); | ||
233 | goto err_tll; | ||
234 | } | 233 | } |
235 | 234 | ||
236 | tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); | 235 | tll->pdata = pdata; |
237 | if (IS_ERR(tll->usbtll_p2_fck)) { | ||
238 | ret = PTR_ERR(tll->usbtll_p2_fck); | ||
239 | dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); | ||
240 | goto err_usbtll_p1_fck; | ||
241 | } | ||
242 | 236 | ||
243 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 237 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
244 | if (!res) { | 238 | base = devm_request_and_ioremap(dev, res); |
245 | dev_err(dev, "usb tll get resource failed\n"); | ||
246 | ret = -ENODEV; | ||
247 | goto err_usbtll_p2_fck; | ||
248 | } | ||
249 | |||
250 | base = ioremap(res->start, resource_size(res)); | ||
251 | if (!base) { | 239 | if (!base) { |
252 | dev_err(dev, "TLL ioremap failed\n"); | 240 | ret = -EADDRNOTAVAIL; |
253 | ret = -ENOMEM; | 241 | dev_err(dev, "Resource request/ioremap failed:%d\n", ret); |
254 | goto err_usbtll_p2_fck; | 242 | return ret; |
255 | } | 243 | } |
256 | 244 | ||
257 | platform_set_drvdata(pdev, tll); | 245 | platform_set_drvdata(pdev, tll); |
258 | pm_runtime_enable(dev); | 246 | pm_runtime_enable(dev); |
259 | pm_runtime_get_sync(dev); | 247 | pm_runtime_get_sync(dev); |
260 | 248 | ||
261 | spin_lock_irqsave(&tll->lock, flags); | ||
262 | |||
263 | ver = usbtll_read(base, OMAP_USBTLL_REVISION); | 249 | ver = usbtll_read(base, OMAP_USBTLL_REVISION); |
264 | switch (ver) { | 250 | switch (ver) { |
265 | case OMAP_USBTLL_REV1: | 251 | case OMAP_USBTLL_REV1: |
266 | case OMAP_USBTLL_REV2: | 252 | case OMAP_USBTLL_REV4: |
267 | count = OMAP_TLL_CHANNEL_COUNT; | 253 | tll->nch = OMAP_TLL_CHANNEL_COUNT; |
268 | break; | 254 | break; |
255 | case OMAP_USBTLL_REV2: | ||
269 | case OMAP_USBTLL_REV3: | 256 | case OMAP_USBTLL_REV3: |
270 | count = OMAP_REV2_TLL_CHANNEL_COUNT; | 257 | tll->nch = OMAP_REV2_TLL_CHANNEL_COUNT; |
271 | break; | 258 | break; |
272 | default: | 259 | default: |
273 | dev_err(dev, "TLL version failed\n"); | 260 | tll->nch = OMAP_TLL_CHANNEL_COUNT; |
274 | ret = -ENODEV; | 261 | dev_dbg(dev, |
275 | goto err_ioremap; | 262 | "USB TLL Rev : 0x%x not recognized, assuming %d channels\n", |
263 | ver, tll->nch); | ||
264 | break; | ||
276 | } | 265 | } |
277 | 266 | ||
278 | if (is_ehci_tll_mode(pdata->port_mode[0]) || | 267 | tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk * [tll->nch]), |
279 | is_ehci_tll_mode(pdata->port_mode[1]) || | 268 | GFP_KERNEL); |
280 | is_ehci_tll_mode(pdata->port_mode[2]) || | 269 | if (!tll->ch_clk) { |
281 | is_ohci_port(pdata->port_mode[0]) || | 270 | ret = -ENOMEM; |
282 | is_ohci_port(pdata->port_mode[1]) || | 271 | dev_err(dev, "Couldn't allocate memory for channel clocks\n"); |
283 | is_ohci_port(pdata->port_mode[2])) { | 272 | goto err_clk_alloc; |
273 | } | ||
274 | |||
275 | for (i = 0; i < tll->nch; i++) { | ||
276 | char clkname[] = "usb_tll_hs_usb_chx_clk"; | ||
277 | |||
278 | snprintf(clkname, sizeof(clkname), | ||
279 | "usb_tll_hs_usb_ch%d_clk", i); | ||
280 | tll->ch_clk[i] = clk_get(dev, clkname); | ||
281 | |||
282 | if (IS_ERR(tll->ch_clk[i])) | ||
283 | dev_dbg(dev, "can't get clock : %s\n", clkname); | ||
284 | } | ||
285 | |||
286 | needs_tll = false; | ||
287 | for (i = 0; i < tll->nch; i++) | ||
288 | needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]); | ||
289 | |||
290 | if (needs_tll) { | ||
284 | 291 | ||
285 | /* Program Common TLL register */ | 292 | /* Program Common TLL register */ |
286 | reg = usbtll_read(base, OMAP_TLL_SHARED_CONF); | 293 | reg = usbtll_read(base, OMAP_TLL_SHARED_CONF); |
@@ -292,7 +299,7 @@ static int usbtll_omap_probe(struct platform_device *pdev) | |||
292 | usbtll_write(base, OMAP_TLL_SHARED_CONF, reg); | 299 | usbtll_write(base, OMAP_TLL_SHARED_CONF, reg); |
293 | 300 | ||
294 | /* Enable channels now */ | 301 | /* Enable channels now */ |
295 | for (i = 0; i < count; i++) { | 302 | for (i = 0; i < tll->nch; i++) { |
296 | reg = usbtll_read(base, OMAP_TLL_CHANNEL_CONF(i)); | 303 | reg = usbtll_read(base, OMAP_TLL_CHANNEL_CONF(i)); |
297 | 304 | ||
298 | if (is_ohci_port(pdata->port_mode[i])) { | 305 | if (is_ohci_port(pdata->port_mode[i])) { |
@@ -308,6 +315,15 @@ static int usbtll_omap_probe(struct platform_device *pdev) | |||
308 | reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE | 315 | reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE |
309 | | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF | 316 | | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF |
310 | | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); | 317 | | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); |
318 | } else if (pdata->port_mode[i] == | ||
319 | OMAP_EHCI_PORT_MODE_HSIC) { | ||
320 | /* | ||
321 | * HSIC Mode requires UTMI port configurations | ||
322 | */ | ||
323 | reg |= OMAP_TLL_CHANNEL_CONF_DRVVBUS | ||
324 | | OMAP_TLL_CHANNEL_CONF_CHRGVBUS | ||
325 | | OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI | ||
326 | | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF; | ||
311 | } else { | 327 | } else { |
312 | continue; | 328 | continue; |
313 | } | 329 | } |
@@ -320,25 +336,18 @@ static int usbtll_omap_probe(struct platform_device *pdev) | |||
320 | } | 336 | } |
321 | } | 337 | } |
322 | 338 | ||
323 | err_ioremap: | ||
324 | spin_unlock_irqrestore(&tll->lock, flags); | ||
325 | iounmap(base); | ||
326 | pm_runtime_put_sync(dev); | 339 | pm_runtime_put_sync(dev); |
327 | tll_pdev = pdev; | 340 | /* only after this can omap_tll_enable/disable work */ |
328 | if (!ret) | 341 | spin_lock(&tll_lock); |
329 | goto end; | 342 | tll_dev = dev; |
330 | pm_runtime_disable(dev); | 343 | spin_unlock(&tll_lock); |
331 | 344 | ||
332 | err_usbtll_p2_fck: | 345 | return 0; |
333 | clk_put(tll->usbtll_p2_fck); | ||
334 | |||
335 | err_usbtll_p1_fck: | ||
336 | clk_put(tll->usbtll_p1_fck); | ||
337 | 346 | ||
338 | err_tll: | 347 | err_clk_alloc: |
339 | kfree(tll); | 348 | pm_runtime_put_sync(dev); |
349 | pm_runtime_disable(dev); | ||
340 | 350 | ||
341 | end: | ||
342 | return ret; | 351 | return ret; |
343 | } | 352 | } |
344 | 353 | ||
@@ -351,36 +360,42 @@ end: | |||
351 | static int usbtll_omap_remove(struct platform_device *pdev) | 360 | static int usbtll_omap_remove(struct platform_device *pdev) |
352 | { | 361 | { |
353 | struct usbtll_omap *tll = platform_get_drvdata(pdev); | 362 | struct usbtll_omap *tll = platform_get_drvdata(pdev); |
363 | int i; | ||
364 | |||
365 | spin_lock(&tll_lock); | ||
366 | tll_dev = NULL; | ||
367 | spin_unlock(&tll_lock); | ||
368 | |||
369 | for (i = 0; i < tll->nch; i++) | ||
370 | if (!IS_ERR(tll->ch_clk[i])) | ||
371 | clk_put(tll->ch_clk[i]); | ||
354 | 372 | ||
355 | clk_put(tll->usbtll_p2_fck); | ||
356 | clk_put(tll->usbtll_p1_fck); | ||
357 | pm_runtime_disable(&pdev->dev); | 373 | pm_runtime_disable(&pdev->dev); |
358 | kfree(tll); | ||
359 | return 0; | 374 | return 0; |
360 | } | 375 | } |
361 | 376 | ||
362 | static int usbtll_runtime_resume(struct device *dev) | 377 | static int usbtll_runtime_resume(struct device *dev) |
363 | { | 378 | { |
364 | struct usbtll_omap *tll = dev_get_drvdata(dev); | 379 | struct usbtll_omap *tll = dev_get_drvdata(dev); |
365 | struct usbtll_omap_platform_data *pdata = &tll->platdata; | 380 | struct usbhs_omap_platform_data *pdata = tll->pdata; |
366 | unsigned long flags; | 381 | int i; |
367 | 382 | ||
368 | dev_dbg(dev, "usbtll_runtime_resume\n"); | 383 | dev_dbg(dev, "usbtll_runtime_resume\n"); |
369 | 384 | ||
370 | if (!pdata) { | 385 | for (i = 0; i < tll->nch; i++) { |
371 | dev_dbg(dev, "missing platform_data\n"); | 386 | if (omap_usb_mode_needs_tll(pdata->port_mode[i])) { |
372 | return -ENODEV; | 387 | int r; |
373 | } | ||
374 | |||
375 | spin_lock_irqsave(&tll->lock, flags); | ||
376 | 388 | ||
377 | if (is_ehci_tll_mode(pdata->port_mode[0])) | 389 | if (IS_ERR(tll->ch_clk[i])) |
378 | clk_enable(tll->usbtll_p1_fck); | 390 | continue; |
379 | |||
380 | if (is_ehci_tll_mode(pdata->port_mode[1])) | ||
381 | clk_enable(tll->usbtll_p2_fck); | ||
382 | 391 | ||
383 | spin_unlock_irqrestore(&tll->lock, flags); | 392 | r = clk_enable(tll->ch_clk[i]); |
393 | if (r) { | ||
394 | dev_err(dev, | ||
395 | "Error enabling ch %d clock: %d\n", i, r); | ||
396 | } | ||
397 | } | ||
398 | } | ||
384 | 399 | ||
385 | return 0; | 400 | return 0; |
386 | } | 401 | } |
@@ -388,26 +403,18 @@ static int usbtll_runtime_resume(struct device *dev) | |||
388 | static int usbtll_runtime_suspend(struct device *dev) | 403 | static int usbtll_runtime_suspend(struct device *dev) |
389 | { | 404 | { |
390 | struct usbtll_omap *tll = dev_get_drvdata(dev); | 405 | struct usbtll_omap *tll = dev_get_drvdata(dev); |
391 | struct usbtll_omap_platform_data *pdata = &tll->platdata; | 406 | struct usbhs_omap_platform_data *pdata = tll->pdata; |
392 | unsigned long flags; | 407 | int i; |
393 | 408 | ||
394 | dev_dbg(dev, "usbtll_runtime_suspend\n"); | 409 | dev_dbg(dev, "usbtll_runtime_suspend\n"); |
395 | 410 | ||
396 | if (!pdata) { | 411 | for (i = 0; i < tll->nch; i++) { |
397 | dev_dbg(dev, "missing platform_data\n"); | 412 | if (omap_usb_mode_needs_tll(pdata->port_mode[i])) { |
398 | return -ENODEV; | 413 | if (!IS_ERR(tll->ch_clk[i])) |
414 | clk_disable(tll->ch_clk[i]); | ||
415 | } | ||
399 | } | 416 | } |
400 | 417 | ||
401 | spin_lock_irqsave(&tll->lock, flags); | ||
402 | |||
403 | if (is_ehci_tll_mode(pdata->port_mode[0])) | ||
404 | clk_disable(tll->usbtll_p1_fck); | ||
405 | |||
406 | if (is_ehci_tll_mode(pdata->port_mode[1])) | ||
407 | clk_disable(tll->usbtll_p2_fck); | ||
408 | |||
409 | spin_unlock_irqrestore(&tll->lock, flags); | ||
410 | |||
411 | return 0; | 418 | return 0; |
412 | } | 419 | } |
413 | 420 | ||
@@ -429,21 +436,39 @@ static struct platform_driver usbtll_omap_driver = { | |||
429 | 436 | ||
430 | int omap_tll_enable(void) | 437 | int omap_tll_enable(void) |
431 | { | 438 | { |
432 | if (!tll_pdev) { | 439 | int ret; |
433 | pr_err("missing omap usbhs tll platform_data\n"); | 440 | |
434 | return -ENODEV; | 441 | spin_lock(&tll_lock); |
442 | |||
443 | if (!tll_dev) { | ||
444 | pr_err("%s: OMAP USB TLL not initialized\n", __func__); | ||
445 | ret = -ENODEV; | ||
446 | } else { | ||
447 | ret = pm_runtime_get_sync(tll_dev); | ||
435 | } | 448 | } |
436 | return pm_runtime_get_sync(&tll_pdev->dev); | 449 | |
450 | spin_unlock(&tll_lock); | ||
451 | |||
452 | return ret; | ||
437 | } | 453 | } |
438 | EXPORT_SYMBOL_GPL(omap_tll_enable); | 454 | EXPORT_SYMBOL_GPL(omap_tll_enable); |
439 | 455 | ||
440 | int omap_tll_disable(void) | 456 | int omap_tll_disable(void) |
441 | { | 457 | { |
442 | if (!tll_pdev) { | 458 | int ret; |
443 | pr_err("missing omap usbhs tll platform_data\n"); | 459 | |
444 | return -ENODEV; | 460 | spin_lock(&tll_lock); |
461 | |||
462 | if (!tll_dev) { | ||
463 | pr_err("%s: OMAP USB TLL not initialized\n", __func__); | ||
464 | ret = -ENODEV; | ||
465 | } else { | ||
466 | ret = pm_runtime_put_sync(tll_dev); | ||
445 | } | 467 | } |
446 | return pm_runtime_put_sync(&tll_pdev->dev); | 468 | |
469 | spin_unlock(&tll_lock); | ||
470 | |||
471 | return ret; | ||
447 | } | 472 | } |
448 | EXPORT_SYMBOL_GPL(omap_tll_disable); | 473 | EXPORT_SYMBOL_GPL(omap_tll_disable); |
449 | 474 | ||
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 6ffd7a2affdc..bbdbc50a3cca 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c | |||
@@ -39,6 +39,14 @@ enum palmas_ids { | |||
39 | PALMAS_USB_ID, | 39 | PALMAS_USB_ID, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static struct resource palmas_rtc_resources[] = { | ||
43 | { | ||
44 | .start = PALMAS_RTC_ALARM_IRQ, | ||
45 | .end = PALMAS_RTC_ALARM_IRQ, | ||
46 | .flags = IORESOURCE_IRQ, | ||
47 | }, | ||
48 | }; | ||
49 | |||
42 | static const struct mfd_cell palmas_children[] = { | 50 | static const struct mfd_cell palmas_children[] = { |
43 | { | 51 | { |
44 | .name = "palmas-pmic", | 52 | .name = "palmas-pmic", |
@@ -59,6 +67,8 @@ static const struct mfd_cell palmas_children[] = { | |||
59 | { | 67 | { |
60 | .name = "palmas-rtc", | 68 | .name = "palmas-rtc", |
61 | .id = PALMAS_RTC_ID, | 69 | .id = PALMAS_RTC_ID, |
70 | .resources = &palmas_rtc_resources[0], | ||
71 | .num_resources = ARRAY_SIZE(palmas_rtc_resources), | ||
62 | }, | 72 | }, |
63 | { | 73 | { |
64 | .name = "palmas-pwrbutton", | 74 | .name = "palmas-pwrbutton", |
@@ -456,8 +466,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c, | |||
456 | 466 | ||
457 | ret = mfd_add_devices(palmas->dev, -1, | 467 | ret = mfd_add_devices(palmas->dev, -1, |
458 | children, ARRAY_SIZE(palmas_children), | 468 | children, ARRAY_SIZE(palmas_children), |
459 | NULL, regmap_irq_chip_get_base(palmas->irq_data), | 469 | NULL, 0, |
460 | NULL); | 470 | regmap_irq_get_domain(palmas->irq_data)); |
461 | kfree(children); | 471 | kfree(children); |
462 | 472 | ||
463 | if (ret < 0) | 473 | if (ret < 0) |
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 3d3b4addf81a..2a2d31687b72 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c | |||
@@ -115,14 +115,24 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) | |||
115 | static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | 115 | static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) |
116 | { | 116 | { |
117 | u8 mask, val; | 117 | u8 mask, val; |
118 | int err; | ||
118 | 119 | ||
119 | mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; | 120 | mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; |
120 | if (voltage == OUTPUT_3V3) | 121 | if (voltage == OUTPUT_3V3) { |
122 | err = rtsx_pci_write_register(pcr, | ||
123 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); | ||
124 | if (err < 0) | ||
125 | return err; | ||
121 | val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; | 126 | val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; |
122 | else if (voltage == OUTPUT_1V8) | 127 | } else if (voltage == OUTPUT_1V8) { |
128 | err = rtsx_pci_write_register(pcr, | ||
129 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); | ||
130 | if (err < 0) | ||
131 | return err; | ||
123 | val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; | 132 | val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; |
124 | else | 133 | } else { |
125 | return -EINVAL; | 134 | return -EINVAL; |
135 | } | ||
126 | 136 | ||
127 | return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); | 137 | return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); |
128 | } | 138 | } |
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 98fe0f39463e..ec78d9fb0879 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c | |||
@@ -149,10 +149,18 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | |||
149 | int err; | 149 | int err; |
150 | 150 | ||
151 | if (voltage == OUTPUT_3V3) { | 151 | if (voltage == OUTPUT_3V3) { |
152 | err = rtsx_pci_write_register(pcr, | ||
153 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); | ||
154 | if (err < 0) | ||
155 | return err; | ||
152 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); | 156 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); |
153 | if (err < 0) | 157 | if (err < 0) |
154 | return err; | 158 | return err; |
155 | } else if (voltage == OUTPUT_1V8) { | 159 | } else if (voltage == OUTPUT_1V8) { |
160 | err = rtsx_pci_write_register(pcr, | ||
161 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); | ||
162 | if (err < 0) | ||
163 | return err; | ||
156 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); | 164 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); |
157 | if (err < 0) | 165 | if (err < 0) |
158 | return err; | 166 | return err; |
diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c new file mode 100644 index 000000000000..fc831dcb1480 --- /dev/null +++ b/drivers/mfd/rts5227.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* Driver for Realtek PCI-Express card reader | ||
2 | * | ||
3 | * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2, or (at your option) any | ||
8 | * later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Author: | ||
19 | * Wei WANG <wei_wang@realsil.com.cn> | ||
20 | * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China | ||
21 | * | ||
22 | * Roger Tseng <rogerable@realtek.com> | ||
23 | * No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/mfd/rtsx_pci.h> | ||
29 | |||
30 | #include "rtsx_pcr.h" | ||
31 | |||
32 | static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) | ||
33 | { | ||
34 | u16 cap; | ||
35 | |||
36 | rtsx_pci_init_cmd(pcr); | ||
37 | |||
38 | /* Configure GPIO as output */ | ||
39 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); | ||
40 | /* Switch LDO3318 source from DV33 to card_3v3 */ | ||
41 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); | ||
42 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); | ||
43 | /* LED shine disabled, set initial shine cycle period */ | ||
44 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); | ||
45 | /* Configure LTR */ | ||
46 | pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap); | ||
47 | if (cap & PCI_EXP_LTR_EN) | ||
48 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3); | ||
49 | /* Configure OBFF */ | ||
50 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03); | ||
51 | /* Configure force_clock_req | ||
52 | * Maybe We should define 0xFF03 as some name | ||
53 | */ | ||
54 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFF03, 0x08, 0x08); | ||
55 | /* Correct driving */ | ||
56 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
57 | SD30_CLK_DRIVE_SEL, 0xFF, 0x96); | ||
58 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
59 | SD30_CMD_DRIVE_SEL, 0xFF, 0x96); | ||
60 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
61 | SD30_DAT_DRIVE_SEL, 0xFF, 0x96); | ||
62 | |||
63 | return rtsx_pci_send_cmd(pcr, 100); | ||
64 | } | ||
65 | |||
66 | static int rts5227_optimize_phy(struct rtsx_pcr *pcr) | ||
67 | { | ||
68 | /* Optimize RX sensitivity */ | ||
69 | return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42); | ||
70 | } | ||
71 | |||
72 | static int rts5227_turn_on_led(struct rtsx_pcr *pcr) | ||
73 | { | ||
74 | return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02); | ||
75 | } | ||
76 | |||
77 | static int rts5227_turn_off_led(struct rtsx_pcr *pcr) | ||
78 | { | ||
79 | return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00); | ||
80 | } | ||
81 | |||
82 | static int rts5227_enable_auto_blink(struct rtsx_pcr *pcr) | ||
83 | { | ||
84 | return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08); | ||
85 | } | ||
86 | |||
87 | static int rts5227_disable_auto_blink(struct rtsx_pcr *pcr) | ||
88 | { | ||
89 | return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00); | ||
90 | } | ||
91 | |||
92 | static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card) | ||
93 | { | ||
94 | int err; | ||
95 | |||
96 | rtsx_pci_init_cmd(pcr); | ||
97 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, | ||
98 | SD_POWER_MASK, SD_PARTIAL_POWER_ON); | ||
99 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, | ||
100 | LDO3318_PWR_MASK, 0x02); | ||
101 | err = rtsx_pci_send_cmd(pcr, 100); | ||
102 | if (err < 0) | ||
103 | return err; | ||
104 | |||
105 | /* To avoid too large in-rush current */ | ||
106 | udelay(150); | ||
107 | |||
108 | rtsx_pci_init_cmd(pcr); | ||
109 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, | ||
110 | SD_POWER_MASK, SD_POWER_ON); | ||
111 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, | ||
112 | LDO3318_PWR_MASK, 0x06); | ||
113 | err = rtsx_pci_send_cmd(pcr, 100); | ||
114 | if (err < 0) | ||
115 | return err; | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card) | ||
121 | { | ||
122 | rtsx_pci_init_cmd(pcr); | ||
123 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, | ||
124 | SD_POWER_MASK | PMOS_STRG_MASK, | ||
125 | SD_POWER_OFF | PMOS_STRG_400mA); | ||
126 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, | ||
127 | LDO3318_PWR_MASK, 0X00); | ||
128 | return rtsx_pci_send_cmd(pcr, 100); | ||
129 | } | ||
130 | |||
131 | static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | ||
132 | { | ||
133 | int err; | ||
134 | u8 drive_sel; | ||
135 | |||
136 | if (voltage == OUTPUT_3V3) { | ||
137 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); | ||
138 | if (err < 0) | ||
139 | return err; | ||
140 | drive_sel = 0x96; | ||
141 | } else if (voltage == OUTPUT_1V8) { | ||
142 | err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02); | ||
143 | if (err < 0) | ||
144 | return err; | ||
145 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24); | ||
146 | if (err < 0) | ||
147 | return err; | ||
148 | drive_sel = 0xB3; | ||
149 | } else { | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | /* set pad drive */ | ||
154 | rtsx_pci_init_cmd(pcr); | ||
155 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, | ||
156 | 0xFF, drive_sel); | ||
157 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, | ||
158 | 0xFF, drive_sel); | ||
159 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, | ||
160 | 0xFF, drive_sel); | ||
161 | return rtsx_pci_send_cmd(pcr, 100); | ||
162 | } | ||
163 | |||
164 | static const struct pcr_ops rts5227_pcr_ops = { | ||
165 | .extra_init_hw = rts5227_extra_init_hw, | ||
166 | .optimize_phy = rts5227_optimize_phy, | ||
167 | .turn_on_led = rts5227_turn_on_led, | ||
168 | .turn_off_led = rts5227_turn_off_led, | ||
169 | .enable_auto_blink = rts5227_enable_auto_blink, | ||
170 | .disable_auto_blink = rts5227_disable_auto_blink, | ||
171 | .card_power_on = rts5227_card_power_on, | ||
172 | .card_power_off = rts5227_card_power_off, | ||
173 | .switch_output_voltage = rts5227_switch_output_voltage, | ||
174 | .cd_deglitch = NULL, | ||
175 | .conv_clk_and_div_n = NULL, | ||
176 | }; | ||
177 | |||
178 | /* SD Pull Control Enable: | ||
179 | * SD_DAT[3:0] ==> pull up | ||
180 | * SD_CD ==> pull up | ||
181 | * SD_WP ==> pull up | ||
182 | * SD_CMD ==> pull up | ||
183 | * SD_CLK ==> pull down | ||
184 | */ | ||
185 | static const u32 rts5227_sd_pull_ctl_enable_tbl[] = { | ||
186 | RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), | ||
187 | RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9), | ||
188 | 0, | ||
189 | }; | ||
190 | |||
191 | /* SD Pull Control Disable: | ||
192 | * SD_DAT[3:0] ==> pull down | ||
193 | * SD_CD ==> pull up | ||
194 | * SD_WP ==> pull down | ||
195 | * SD_CMD ==> pull down | ||
196 | * SD_CLK ==> pull down | ||
197 | */ | ||
198 | static const u32 rts5227_sd_pull_ctl_disable_tbl[] = { | ||
199 | RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), | ||
200 | RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5), | ||
201 | 0, | ||
202 | }; | ||
203 | |||
204 | /* MS Pull Control Enable: | ||
205 | * MS CD ==> pull up | ||
206 | * others ==> pull down | ||
207 | */ | ||
208 | static const u32 rts5227_ms_pull_ctl_enable_tbl[] = { | ||
209 | RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), | ||
210 | RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), | ||
211 | 0, | ||
212 | }; | ||
213 | |||
214 | /* MS Pull Control Disable: | ||
215 | * MS CD ==> pull up | ||
216 | * others ==> pull down | ||
217 | */ | ||
218 | static const u32 rts5227_ms_pull_ctl_disable_tbl[] = { | ||
219 | RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), | ||
220 | RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), | ||
221 | 0, | ||
222 | }; | ||
223 | |||
224 | void rts5227_init_params(struct rtsx_pcr *pcr) | ||
225 | { | ||
226 | pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; | ||
227 | pcr->num_slots = 2; | ||
228 | pcr->ops = &rts5227_pcr_ops; | ||
229 | |||
230 | pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl; | ||
231 | pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl; | ||
232 | pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl; | ||
233 | pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl; | ||
234 | } | ||
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index 29d889cbb9c5..58af4dbe3586 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c | |||
@@ -119,10 +119,18 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | |||
119 | int err; | 119 | int err; |
120 | 120 | ||
121 | if (voltage == OUTPUT_3V3) { | 121 | if (voltage == OUTPUT_3V3) { |
122 | err = rtsx_pci_write_register(pcr, | ||
123 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); | ||
124 | if (err < 0) | ||
125 | return err; | ||
122 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); | 126 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); |
123 | if (err < 0) | 127 | if (err < 0) |
124 | return err; | 128 | return err; |
125 | } else if (voltage == OUTPUT_1V8) { | 129 | } else if (voltage == OUTPUT_1V8) { |
130 | err = rtsx_pci_write_register(pcr, | ||
131 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); | ||
132 | if (err < 0) | ||
133 | return err; | ||
126 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); | 134 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); |
127 | if (err < 0) | 135 | if (err < 0) |
128 | return err; | 136 | return err; |
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 9fc57009e228..481a98a10ecd 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c | |||
@@ -55,6 +55,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = { | |||
55 | { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 }, | 55 | { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
56 | { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, | 56 | { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
57 | { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, | 57 | { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, |
58 | { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, | ||
58 | { 0, } | 59 | { 0, } |
59 | }; | 60 | }; |
60 | 61 | ||
@@ -325,7 +326,6 @@ static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr, | |||
325 | val = ((u64)addr << 32) | ((u64)len << 12) | option; | 326 | val = ((u64)addr << 32) | ((u64)len << 12) | option; |
326 | 327 | ||
327 | put_unaligned_le64(val, ptr); | 328 | put_unaligned_le64(val, ptr); |
328 | ptr++; | ||
329 | pcr->sgi++; | 329 | pcr->sgi++; |
330 | } | 330 | } |
331 | 331 | ||
@@ -591,8 +591,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, | |||
591 | u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk) | 591 | u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk) |
592 | { | 592 | { |
593 | int err, clk; | 593 | int err, clk; |
594 | u8 N, min_N, max_N, clk_divider; | 594 | u8 n, clk_divider, mcu_cnt, div; |
595 | u8 mcu_cnt, div, max_div; | ||
596 | u8 depth[] = { | 595 | u8 depth[] = { |
597 | [RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M, | 596 | [RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M, |
598 | [RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M, | 597 | [RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M, |
@@ -616,10 +615,6 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, | |||
616 | card_clock /= 1000000; | 615 | card_clock /= 1000000; |
617 | dev_dbg(&(pcr->pci->dev), "Switch card clock to %dMHz\n", card_clock); | 616 | dev_dbg(&(pcr->pci->dev), "Switch card clock to %dMHz\n", card_clock); |
618 | 617 | ||
619 | min_N = 80; | ||
620 | max_N = 208; | ||
621 | max_div = CLK_DIV_8; | ||
622 | |||
623 | clk = card_clock; | 618 | clk = card_clock; |
624 | if (!initial_mode && double_clk) | 619 | if (!initial_mode && double_clk) |
625 | clk = card_clock * 2; | 620 | clk = card_clock * 2; |
@@ -631,30 +626,30 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, | |||
631 | return 0; | 626 | return 0; |
632 | 627 | ||
633 | if (pcr->ops->conv_clk_and_div_n) | 628 | if (pcr->ops->conv_clk_and_div_n) |
634 | N = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N); | 629 | n = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N); |
635 | else | 630 | else |
636 | N = (u8)(clk - 2); | 631 | n = (u8)(clk - 2); |
637 | if ((clk <= 2) || (N > max_N)) | 632 | if ((clk <= 2) || (n > MAX_DIV_N_PCR)) |
638 | return -EINVAL; | 633 | return -EINVAL; |
639 | 634 | ||
640 | mcu_cnt = (u8)(125/clk + 3); | 635 | mcu_cnt = (u8)(125/clk + 3); |
641 | if (mcu_cnt > 15) | 636 | if (mcu_cnt > 15) |
642 | mcu_cnt = 15; | 637 | mcu_cnt = 15; |
643 | 638 | ||
644 | /* Make sure that the SSC clock div_n is equal or greater than min_N */ | 639 | /* Make sure that the SSC clock div_n is not less than MIN_DIV_N_PCR */ |
645 | div = CLK_DIV_1; | 640 | div = CLK_DIV_1; |
646 | while ((N < min_N) && (div < max_div)) { | 641 | while ((n < MIN_DIV_N_PCR) && (div < CLK_DIV_8)) { |
647 | if (pcr->ops->conv_clk_and_div_n) { | 642 | if (pcr->ops->conv_clk_and_div_n) { |
648 | int dbl_clk = pcr->ops->conv_clk_and_div_n(N, | 643 | int dbl_clk = pcr->ops->conv_clk_and_div_n(n, |
649 | DIV_N_TO_CLK) * 2; | 644 | DIV_N_TO_CLK) * 2; |
650 | N = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk, | 645 | n = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk, |
651 | CLK_TO_DIV_N); | 646 | CLK_TO_DIV_N); |
652 | } else { | 647 | } else { |
653 | N = (N + 2) * 2 - 2; | 648 | n = (n + 2) * 2 - 2; |
654 | } | 649 | } |
655 | div++; | 650 | div++; |
656 | } | 651 | } |
657 | dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div); | 652 | dev_dbg(&(pcr->pci->dev), "n = %d, div = %d\n", n, div); |
658 | 653 | ||
659 | ssc_depth = depth[ssc_depth]; | 654 | ssc_depth = depth[ssc_depth]; |
660 | if (double_clk) | 655 | if (double_clk) |
@@ -671,7 +666,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, | |||
671 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); | 666 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); |
672 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, | 667 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, |
673 | SSC_DEPTH_MASK, ssc_depth); | 668 | SSC_DEPTH_MASK, ssc_depth); |
674 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N); | 669 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n); |
675 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); | 670 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); |
676 | if (vpclk) { | 671 | if (vpclk) { |
677 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, | 672 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, |
@@ -713,6 +708,25 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card) | |||
713 | } | 708 | } |
714 | EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); | 709 | EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); |
715 | 710 | ||
711 | int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card) | ||
712 | { | ||
713 | unsigned int cd_mask[] = { | ||
714 | [RTSX_SD_CARD] = SD_EXIST, | ||
715 | [RTSX_MS_CARD] = MS_EXIST | ||
716 | }; | ||
717 | |||
718 | if (!pcr->ms_pmos) { | ||
719 | /* When using single PMOS, accessing card is not permitted | ||
720 | * if the existing card is not the designated one. | ||
721 | */ | ||
722 | if (pcr->card_exist & (~cd_mask[card])) | ||
723 | return -EIO; | ||
724 | } | ||
725 | |||
726 | return 0; | ||
727 | } | ||
728 | EXPORT_SYMBOL_GPL(rtsx_pci_card_exclusive_check); | ||
729 | |||
716 | int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | 730 | int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) |
717 | { | 731 | { |
718 | if (pcr->ops->switch_output_voltage) | 732 | if (pcr->ops->switch_output_voltage) |
@@ -758,7 +772,7 @@ static void rtsx_pci_card_detect(struct work_struct *work) | |||
758 | struct delayed_work *dwork; | 772 | struct delayed_work *dwork; |
759 | struct rtsx_pcr *pcr; | 773 | struct rtsx_pcr *pcr; |
760 | unsigned long flags; | 774 | unsigned long flags; |
761 | unsigned int card_detect = 0; | 775 | unsigned int card_detect = 0, card_inserted, card_removed; |
762 | u32 irq_status; | 776 | u32 irq_status; |
763 | 777 | ||
764 | dwork = to_delayed_work(work); | 778 | dwork = to_delayed_work(work); |
@@ -766,25 +780,35 @@ static void rtsx_pci_card_detect(struct work_struct *work) | |||
766 | 780 | ||
767 | dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__); | 781 | dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__); |
768 | 782 | ||
783 | mutex_lock(&pcr->pcr_mutex); | ||
769 | spin_lock_irqsave(&pcr->lock, flags); | 784 | spin_lock_irqsave(&pcr->lock, flags); |
770 | 785 | ||
771 | irq_status = rtsx_pci_readl(pcr, RTSX_BIPR); | 786 | irq_status = rtsx_pci_readl(pcr, RTSX_BIPR); |
772 | dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status); | 787 | dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status); |
773 | 788 | ||
774 | if (pcr->card_inserted || pcr->card_removed) { | 789 | irq_status &= CARD_EXIST; |
790 | card_inserted = pcr->card_inserted & irq_status; | ||
791 | card_removed = pcr->card_removed; | ||
792 | pcr->card_inserted = 0; | ||
793 | pcr->card_removed = 0; | ||
794 | |||
795 | spin_unlock_irqrestore(&pcr->lock, flags); | ||
796 | |||
797 | if (card_inserted || card_removed) { | ||
775 | dev_dbg(&(pcr->pci->dev), | 798 | dev_dbg(&(pcr->pci->dev), |
776 | "card_inserted: 0x%x, card_removed: 0x%x\n", | 799 | "card_inserted: 0x%x, card_removed: 0x%x\n", |
777 | pcr->card_inserted, pcr->card_removed); | 800 | card_inserted, card_removed); |
778 | 801 | ||
779 | if (pcr->ops->cd_deglitch) | 802 | if (pcr->ops->cd_deglitch) |
780 | pcr->card_inserted = pcr->ops->cd_deglitch(pcr); | 803 | card_inserted = pcr->ops->cd_deglitch(pcr); |
804 | |||
805 | card_detect = card_inserted | card_removed; | ||
781 | 806 | ||
782 | card_detect = pcr->card_inserted | pcr->card_removed; | 807 | pcr->card_exist |= card_inserted; |
783 | pcr->card_inserted = 0; | 808 | pcr->card_exist &= ~card_removed; |
784 | pcr->card_removed = 0; | ||
785 | } | 809 | } |
786 | 810 | ||
787 | spin_unlock_irqrestore(&pcr->lock, flags); | 811 | mutex_unlock(&pcr->pcr_mutex); |
788 | 812 | ||
789 | if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event) | 813 | if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event) |
790 | pcr->slots[RTSX_SD_CARD].card_event( | 814 | pcr->slots[RTSX_SD_CARD].card_event( |
@@ -836,10 +860,6 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
836 | } | 860 | } |
837 | } | 861 | } |
838 | 862 | ||
839 | if (pcr->card_inserted || pcr->card_removed) | ||
840 | schedule_delayed_work(&pcr->carddet_work, | ||
841 | msecs_to_jiffies(200)); | ||
842 | |||
843 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { | 863 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { |
844 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { | 864 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { |
845 | pcr->trans_result = TRANS_RESULT_FAIL; | 865 | pcr->trans_result = TRANS_RESULT_FAIL; |
@@ -852,6 +872,10 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
852 | } | 872 | } |
853 | } | 873 | } |
854 | 874 | ||
875 | if (pcr->card_inserted || pcr->card_removed) | ||
876 | schedule_delayed_work(&pcr->carddet_work, | ||
877 | msecs_to_jiffies(200)); | ||
878 | |||
855 | spin_unlock(&pcr->lock); | 879 | spin_unlock(&pcr->lock); |
856 | return IRQ_HANDLED; | 880 | return IRQ_HANDLED; |
857 | } | 881 | } |
@@ -974,6 +998,14 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) | |||
974 | return err; | 998 | return err; |
975 | } | 999 | } |
976 | 1000 | ||
1001 | /* No CD interrupt if probing driver with card inserted. | ||
1002 | * So we need to initialize pcr->card_exist here. | ||
1003 | */ | ||
1004 | if (pcr->ops->cd_deglitch) | ||
1005 | pcr->card_exist = pcr->ops->cd_deglitch(pcr); | ||
1006 | else | ||
1007 | pcr->card_exist = rtsx_pci_readl(pcr, RTSX_BIPR) & CARD_EXIST; | ||
1008 | |||
977 | return 0; | 1009 | return 0; |
978 | } | 1010 | } |
979 | 1011 | ||
@@ -997,6 +1029,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) | |||
997 | case 0x5289: | 1029 | case 0x5289: |
998 | rtl8411_init_params(pcr); | 1030 | rtl8411_init_params(pcr); |
999 | break; | 1031 | break; |
1032 | |||
1033 | case 0x5227: | ||
1034 | rts5227_init_params(pcr); | ||
1035 | break; | ||
1000 | } | 1036 | } |
1001 | 1037 | ||
1002 | dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n", | 1038 | dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n", |
@@ -1030,6 +1066,10 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, | |||
1030 | pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device, | 1066 | pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device, |
1031 | (int)pcidev->revision); | 1067 | (int)pcidev->revision); |
1032 | 1068 | ||
1069 | ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)); | ||
1070 | if (ret < 0) | ||
1071 | return ret; | ||
1072 | |||
1033 | ret = pci_enable_device(pcidev); | 1073 | ret = pci_enable_device(pcidev); |
1034 | if (ret) | 1074 | if (ret) |
1035 | return ret; | 1075 | return ret; |
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index 12462c1df1a9..2b3ab8a04823 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h | |||
@@ -25,8 +25,12 @@ | |||
25 | 25 | ||
26 | #include <linux/mfd/rtsx_pci.h> | 26 | #include <linux/mfd/rtsx_pci.h> |
27 | 27 | ||
28 | #define MIN_DIV_N_PCR 80 | ||
29 | #define MAX_DIV_N_PCR 208 | ||
30 | |||
28 | void rts5209_init_params(struct rtsx_pcr *pcr); | 31 | void rts5209_init_params(struct rtsx_pcr *pcr); |
29 | void rts5229_init_params(struct rtsx_pcr *pcr); | 32 | void rts5229_init_params(struct rtsx_pcr *pcr); |
30 | void rtl8411_init_params(struct rtsx_pcr *pcr); | 33 | void rtl8411_init_params(struct rtsx_pcr *pcr); |
34 | void rts5227_init_params(struct rtsx_pcr *pcr); | ||
31 | 35 | ||
32 | #endif | 36 | #endif |
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 3f10591ea94e..61aea6381cdf 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
23 | #include <linux/mfd/syscon.h> | ||
23 | 24 | ||
24 | static struct platform_driver syscon_driver; | 25 | static struct platform_driver syscon_driver; |
25 | 26 | ||
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 409afa23d5dc..5ad4b772b097 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/of_device.h> | ||
22 | #include <linux/mfd/core.h> | 23 | #include <linux/mfd/core.h> |
23 | #include <linux/mfd/tps6507x.h> | 24 | #include <linux/mfd/tps6507x.h> |
24 | 25 | ||
@@ -116,11 +117,19 @@ static const struct i2c_device_id tps6507x_i2c_id[] = { | |||
116 | }; | 117 | }; |
117 | MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id); | 118 | MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id); |
118 | 119 | ||
120 | #ifdef CONFIG_OF | ||
121 | static struct of_device_id tps6507x_of_match[] = { | ||
122 | {.compatible = "ti,tps6507x", }, | ||
123 | {}, | ||
124 | }; | ||
125 | MODULE_DEVICE_TABLE(of, tps6507x_of_match); | ||
126 | #endif | ||
119 | 127 | ||
120 | static struct i2c_driver tps6507x_i2c_driver = { | 128 | static struct i2c_driver tps6507x_i2c_driver = { |
121 | .driver = { | 129 | .driver = { |
122 | .name = "tps6507x", | 130 | .name = "tps6507x", |
123 | .owner = THIS_MODULE, | 131 | .owner = THIS_MODULE, |
132 | .of_match_table = of_match_ptr(tps6507x_of_match), | ||
124 | }, | 133 | }, |
125 | .probe = tps6507x_i2c_probe, | 134 | .probe = tps6507x_i2c_probe, |
126 | .remove = tps6507x_i2c_remove, | 135 | .remove = tps6507x_i2c_remove, |
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index 8d12a8e00d9c..98edb5be85c6 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/mfd/core.h> | 26 | #include <linux/mfd/core.h> |
27 | #include <linux/mfd/tps65090.h> | 27 | #include <linux/mfd/tps65090.h> |
28 | #include <linux/of.h> | ||
29 | #include <linux/of_device.h> | ||
28 | #include <linux/err.h> | 30 | #include <linux/err.h> |
29 | 31 | ||
30 | #define NUM_INT_REG 2 | 32 | #define NUM_INT_REG 2 |
@@ -148,18 +150,31 @@ static const struct regmap_config tps65090_regmap_config = { | |||
148 | .volatile_reg = is_volatile_reg, | 150 | .volatile_reg = is_volatile_reg, |
149 | }; | 151 | }; |
150 | 152 | ||
153 | #ifdef CONFIG_OF | ||
154 | static const struct of_device_id tps65090_of_match[] = { | ||
155 | { .compatible = "ti,tps65090",}, | ||
156 | {}, | ||
157 | }; | ||
158 | MODULE_DEVICE_TABLE(of, tps65090_of_match); | ||
159 | #endif | ||
160 | |||
151 | static int tps65090_i2c_probe(struct i2c_client *client, | 161 | static int tps65090_i2c_probe(struct i2c_client *client, |
152 | const struct i2c_device_id *id) | 162 | const struct i2c_device_id *id) |
153 | { | 163 | { |
154 | struct tps65090_platform_data *pdata = client->dev.platform_data; | 164 | struct tps65090_platform_data *pdata = client->dev.platform_data; |
165 | int irq_base = 0; | ||
155 | struct tps65090 *tps65090; | 166 | struct tps65090 *tps65090; |
156 | int ret; | 167 | int ret; |
157 | 168 | ||
158 | if (!pdata) { | 169 | if (!pdata && !client->dev.of_node) { |
159 | dev_err(&client->dev, "tps65090 requires platform data\n"); | 170 | dev_err(&client->dev, |
171 | "tps65090 requires platform data or of_node\n"); | ||
160 | return -EINVAL; | 172 | return -EINVAL; |
161 | } | 173 | } |
162 | 174 | ||
175 | if (pdata) | ||
176 | irq_base = pdata->irq_base; | ||
177 | |||
163 | tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL); | 178 | tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL); |
164 | if (!tps65090) { | 179 | if (!tps65090) { |
165 | dev_err(&client->dev, "mem alloc for tps65090 failed\n"); | 180 | dev_err(&client->dev, "mem alloc for tps65090 failed\n"); |
@@ -178,7 +193,7 @@ static int tps65090_i2c_probe(struct i2c_client *client, | |||
178 | 193 | ||
179 | if (client->irq) { | 194 | if (client->irq) { |
180 | ret = regmap_add_irq_chip(tps65090->rmap, client->irq, | 195 | ret = regmap_add_irq_chip(tps65090->rmap, client->irq, |
181 | IRQF_ONESHOT | IRQF_TRIGGER_LOW, pdata->irq_base, | 196 | IRQF_ONESHOT | IRQF_TRIGGER_LOW, irq_base, |
182 | &tps65090_irq_chip, &tps65090->irq_data); | 197 | &tps65090_irq_chip, &tps65090->irq_data); |
183 | if (ret) { | 198 | if (ret) { |
184 | dev_err(&client->dev, | 199 | dev_err(&client->dev, |
@@ -189,7 +204,7 @@ static int tps65090_i2c_probe(struct i2c_client *client, | |||
189 | 204 | ||
190 | ret = mfd_add_devices(tps65090->dev, -1, tps65090s, | 205 | ret = mfd_add_devices(tps65090->dev, -1, tps65090s, |
191 | ARRAY_SIZE(tps65090s), NULL, | 206 | ARRAY_SIZE(tps65090s), NULL, |
192 | regmap_irq_chip_get_base(tps65090->irq_data), NULL); | 207 | 0, regmap_irq_get_domain(tps65090->irq_data)); |
193 | if (ret) { | 208 | if (ret) { |
194 | dev_err(&client->dev, "add mfd devices failed with err: %d\n", | 209 | dev_err(&client->dev, "add mfd devices failed with err: %d\n", |
195 | ret); | 210 | ret); |
@@ -215,28 +230,6 @@ static int tps65090_i2c_remove(struct i2c_client *client) | |||
215 | return 0; | 230 | return 0; |
216 | } | 231 | } |
217 | 232 | ||
218 | #ifdef CONFIG_PM_SLEEP | ||
219 | static int tps65090_suspend(struct device *dev) | ||
220 | { | ||
221 | struct i2c_client *client = to_i2c_client(dev); | ||
222 | if (client->irq) | ||
223 | disable_irq(client->irq); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int tps65090_resume(struct device *dev) | ||
228 | { | ||
229 | struct i2c_client *client = to_i2c_client(dev); | ||
230 | if (client->irq) | ||
231 | enable_irq(client->irq); | ||
232 | return 0; | ||
233 | } | ||
234 | #endif | ||
235 | |||
236 | static const struct dev_pm_ops tps65090_pm_ops = { | ||
237 | SET_SYSTEM_SLEEP_PM_OPS(tps65090_suspend, tps65090_resume) | ||
238 | }; | ||
239 | |||
240 | static const struct i2c_device_id tps65090_id_table[] = { | 233 | static const struct i2c_device_id tps65090_id_table[] = { |
241 | { "tps65090", 0 }, | 234 | { "tps65090", 0 }, |
242 | { }, | 235 | { }, |
@@ -247,7 +240,7 @@ static struct i2c_driver tps65090_driver = { | |||
247 | .driver = { | 240 | .driver = { |
248 | .name = "tps65090", | 241 | .name = "tps65090", |
249 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
250 | .pm = &tps65090_pm_ops, | 243 | .of_match_table = of_match_ptr(tps65090_of_match), |
251 | }, | 244 | }, |
252 | .probe = tps65090_i2c_probe, | 245 | .probe = tps65090_i2c_probe, |
253 | .remove = tps65090_i2c_remove, | 246 | .remove = tps65090_i2c_remove, |
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 4f3baadd0038..89ab4d970643 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -66,16 +66,6 @@ | |||
66 | 66 | ||
67 | /* Triton Core internal information (BEGIN) */ | 67 | /* Triton Core internal information (BEGIN) */ |
68 | 68 | ||
69 | #define TWL_NUM_SLAVES 4 | ||
70 | |||
71 | #define SUB_CHIP_ID0 0 | ||
72 | #define SUB_CHIP_ID1 1 | ||
73 | #define SUB_CHIP_ID2 2 | ||
74 | #define SUB_CHIP_ID3 3 | ||
75 | #define SUB_CHIP_ID_INVAL 0xff | ||
76 | |||
77 | #define TWL_MODULE_LAST TWL4030_MODULE_LAST | ||
78 | |||
79 | /* Base Address defns for twl4030_map[] */ | 69 | /* Base Address defns for twl4030_map[] */ |
80 | 70 | ||
81 | /* subchip/slave 0 - USB ID */ | 71 | /* subchip/slave 0 - USB ID */ |
@@ -94,10 +84,7 @@ | |||
94 | #define TWL4030_BASEADD_MADC 0x0000 | 84 | #define TWL4030_BASEADD_MADC 0x0000 |
95 | #define TWL4030_BASEADD_MAIN_CHARGE 0x0074 | 85 | #define TWL4030_BASEADD_MAIN_CHARGE 0x0074 |
96 | #define TWL4030_BASEADD_PRECHARGE 0x00AA | 86 | #define TWL4030_BASEADD_PRECHARGE 0x00AA |
97 | #define TWL4030_BASEADD_PWM0 0x00F8 | 87 | #define TWL4030_BASEADD_PWM 0x00F8 |
98 | #define TWL4030_BASEADD_PWM1 0x00FB | ||
99 | #define TWL4030_BASEADD_PWMA 0x00EF | ||
100 | #define TWL4030_BASEADD_PWMB 0x00F1 | ||
101 | #define TWL4030_BASEADD_KEYPAD 0x00D2 | 88 | #define TWL4030_BASEADD_KEYPAD 0x00D2 |
102 | 89 | ||
103 | #define TWL5031_BASEADD_ACCESSORY 0x0074 /* Replaces Main Charge */ | 90 | #define TWL5031_BASEADD_ACCESSORY 0x0074 /* Replaces Main Charge */ |
@@ -117,7 +104,7 @@ | |||
117 | 104 | ||
118 | /* subchip/slave 0 0x48 - POWER */ | 105 | /* subchip/slave 0 0x48 - POWER */ |
119 | #define TWL6030_BASEADD_RTC 0x0000 | 106 | #define TWL6030_BASEADD_RTC 0x0000 |
120 | #define TWL6030_BASEADD_MEM 0x0017 | 107 | #define TWL6030_BASEADD_SECURED_REG 0x0017 |
121 | #define TWL6030_BASEADD_PM_MASTER 0x001F | 108 | #define TWL6030_BASEADD_PM_MASTER 0x001F |
122 | #define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 /* PM_RECEIVER */ | 109 | #define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 /* PM_RECEIVER */ |
123 | #define TWL6030_BASEADD_PM_MISC 0x00E2 | 110 | #define TWL6030_BASEADD_PM_MISC 0x00E2 |
@@ -132,6 +119,7 @@ | |||
132 | #define TWL6030_BASEADD_PIH 0x00D0 | 119 | #define TWL6030_BASEADD_PIH 0x00D0 |
133 | #define TWL6030_BASEADD_CHARGER 0x00E0 | 120 | #define TWL6030_BASEADD_CHARGER 0x00E0 |
134 | #define TWL6025_BASEADD_CHARGER 0x00DA | 121 | #define TWL6025_BASEADD_CHARGER 0x00DA |
122 | #define TWL6030_BASEADD_LED 0x00F4 | ||
135 | 123 | ||
136 | /* subchip/slave 2 0x4A - DFT */ | 124 | /* subchip/slave 2 0x4A - DFT */ |
137 | #define TWL6030_BASEADD_DIEID 0x00C0 | 125 | #define TWL6030_BASEADD_DIEID 0x00C0 |
@@ -153,33 +141,28 @@ | |||
153 | 141 | ||
154 | /*----------------------------------------------------------------------*/ | 142 | /*----------------------------------------------------------------------*/ |
155 | 143 | ||
156 | /* is driver active, bound to a chip? */ | ||
157 | static bool inuse; | ||
158 | |||
159 | /* TWL IDCODE Register value */ | ||
160 | static u32 twl_idcode; | ||
161 | |||
162 | static unsigned int twl_id; | ||
163 | unsigned int twl_rev(void) | ||
164 | { | ||
165 | return twl_id; | ||
166 | } | ||
167 | EXPORT_SYMBOL(twl_rev); | ||
168 | |||
169 | /* Structure for each TWL4030/TWL6030 Slave */ | 144 | /* Structure for each TWL4030/TWL6030 Slave */ |
170 | struct twl_client { | 145 | struct twl_client { |
171 | struct i2c_client *client; | 146 | struct i2c_client *client; |
172 | struct regmap *regmap; | 147 | struct regmap *regmap; |
173 | }; | 148 | }; |
174 | 149 | ||
175 | static struct twl_client twl_modules[TWL_NUM_SLAVES]; | ||
176 | |||
177 | /* mapping the module id to slave id and base address */ | 150 | /* mapping the module id to slave id and base address */ |
178 | struct twl_mapping { | 151 | struct twl_mapping { |
179 | unsigned char sid; /* Slave ID */ | 152 | unsigned char sid; /* Slave ID */ |
180 | unsigned char base; /* base address */ | 153 | unsigned char base; /* base address */ |
181 | }; | 154 | }; |
182 | static struct twl_mapping *twl_map; | 155 | |
156 | struct twl_private { | ||
157 | bool ready; /* The core driver is ready to be used */ | ||
158 | u32 twl_idcode; /* TWL IDCODE Register value */ | ||
159 | unsigned int twl_id; | ||
160 | |||
161 | struct twl_mapping *twl_map; | ||
162 | struct twl_client *twl_modules; | ||
163 | }; | ||
164 | |||
165 | static struct twl_private *twl_priv; | ||
183 | 166 | ||
184 | static struct twl_mapping twl4030_map[] = { | 167 | static struct twl_mapping twl4030_map[] = { |
185 | /* | 168 | /* |
@@ -188,34 +171,33 @@ static struct twl_mapping twl4030_map[] = { | |||
188 | * so they continue to match the order in this table. | 171 | * so they continue to match the order in this table. |
189 | */ | 172 | */ |
190 | 173 | ||
174 | /* Common IPs */ | ||
191 | { 0, TWL4030_BASEADD_USB }, | 175 | { 0, TWL4030_BASEADD_USB }, |
176 | { 1, TWL4030_BASEADD_PIH }, | ||
177 | { 2, TWL4030_BASEADD_MAIN_CHARGE }, | ||
178 | { 3, TWL4030_BASEADD_PM_MASTER }, | ||
179 | { 3, TWL4030_BASEADD_PM_RECEIVER }, | ||
180 | |||
181 | { 3, TWL4030_BASEADD_RTC }, | ||
182 | { 2, TWL4030_BASEADD_PWM }, | ||
183 | { 2, TWL4030_BASEADD_LED }, | ||
184 | { 3, TWL4030_BASEADD_SECURED_REG }, | ||
185 | |||
186 | /* TWL4030 specific IPs */ | ||
192 | { 1, TWL4030_BASEADD_AUDIO_VOICE }, | 187 | { 1, TWL4030_BASEADD_AUDIO_VOICE }, |
193 | { 1, TWL4030_BASEADD_GPIO }, | 188 | { 1, TWL4030_BASEADD_GPIO }, |
194 | { 1, TWL4030_BASEADD_INTBR }, | 189 | { 1, TWL4030_BASEADD_INTBR }, |
195 | { 1, TWL4030_BASEADD_PIH }, | ||
196 | |||
197 | { 1, TWL4030_BASEADD_TEST }, | 190 | { 1, TWL4030_BASEADD_TEST }, |
198 | { 2, TWL4030_BASEADD_KEYPAD }, | 191 | { 2, TWL4030_BASEADD_KEYPAD }, |
192 | |||
199 | { 2, TWL4030_BASEADD_MADC }, | 193 | { 2, TWL4030_BASEADD_MADC }, |
200 | { 2, TWL4030_BASEADD_INTERRUPTS }, | 194 | { 2, TWL4030_BASEADD_INTERRUPTS }, |
201 | { 2, TWL4030_BASEADD_LED }, | ||
202 | |||
203 | { 2, TWL4030_BASEADD_MAIN_CHARGE }, | ||
204 | { 2, TWL4030_BASEADD_PRECHARGE }, | 195 | { 2, TWL4030_BASEADD_PRECHARGE }, |
205 | { 2, TWL4030_BASEADD_PWM0 }, | ||
206 | { 2, TWL4030_BASEADD_PWM1 }, | ||
207 | { 2, TWL4030_BASEADD_PWMA }, | ||
208 | |||
209 | { 2, TWL4030_BASEADD_PWMB }, | ||
210 | { 2, TWL5031_BASEADD_ACCESSORY }, | ||
211 | { 2, TWL5031_BASEADD_INTERRUPTS }, | ||
212 | { 3, TWL4030_BASEADD_BACKUP }, | 196 | { 3, TWL4030_BASEADD_BACKUP }, |
213 | { 3, TWL4030_BASEADD_INT }, | 197 | { 3, TWL4030_BASEADD_INT }, |
214 | 198 | ||
215 | { 3, TWL4030_BASEADD_PM_MASTER }, | 199 | { 2, TWL5031_BASEADD_ACCESSORY }, |
216 | { 3, TWL4030_BASEADD_PM_RECEIVER }, | 200 | { 2, TWL5031_BASEADD_INTERRUPTS }, |
217 | { 3, TWL4030_BASEADD_RTC }, | ||
218 | { 3, TWL4030_BASEADD_SECURED_REG }, | ||
219 | }; | 201 | }; |
220 | 202 | ||
221 | static struct regmap_config twl4030_regmap_config[4] = { | 203 | static struct regmap_config twl4030_regmap_config[4] = { |
@@ -251,35 +233,25 @@ static struct twl_mapping twl6030_map[] = { | |||
251 | * <linux/i2c/twl.h> defines for TWL4030_MODULE_* | 233 | * <linux/i2c/twl.h> defines for TWL4030_MODULE_* |
252 | * so they continue to match the order in this table. | 234 | * so they continue to match the order in this table. |
253 | */ | 235 | */ |
254 | { SUB_CHIP_ID1, TWL6030_BASEADD_USB }, | 236 | |
255 | { SUB_CHIP_ID_INVAL, TWL6030_BASEADD_AUDIO }, | 237 | /* Common IPs */ |
256 | { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID }, | 238 | { 1, TWL6030_BASEADD_USB }, |
257 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | 239 | { 1, TWL6030_BASEADD_PIH }, |
258 | { SUB_CHIP_ID1, TWL6030_BASEADD_PIH }, | 240 | { 1, TWL6030_BASEADD_CHARGER }, |
259 | 241 | { 0, TWL6030_BASEADD_PM_MASTER }, | |
260 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | 242 | { 0, TWL6030_BASEADD_PM_SLAVE_MISC }, |
261 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | 243 | |
262 | { SUB_CHIP_ID1, TWL6030_BASEADD_GPADC_CTRL }, | 244 | { 0, TWL6030_BASEADD_RTC }, |
263 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | 245 | { 1, TWL6030_BASEADD_PWM }, |
264 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | 246 | { 1, TWL6030_BASEADD_LED }, |
265 | 247 | { 0, TWL6030_BASEADD_SECURED_REG }, | |
266 | { SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER }, | 248 | |
267 | { SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE }, | 249 | /* TWL6030 specific IPs */ |
268 | { SUB_CHIP_ID1, TWL6030_BASEADD_PWM }, | 250 | { 0, TWL6030_BASEADD_ZERO }, |
269 | { SUB_CHIP_ID0, TWL6030_BASEADD_ZERO }, | 251 | { 1, TWL6030_BASEADD_ZERO }, |
270 | { SUB_CHIP_ID1, TWL6030_BASEADD_ZERO }, | 252 | { 2, TWL6030_BASEADD_ZERO }, |
271 | 253 | { 1, TWL6030_BASEADD_GPADC_CTRL }, | |
272 | { SUB_CHIP_ID2, TWL6030_BASEADD_ZERO }, | 254 | { 1, TWL6030_BASEADD_GASGAUGE }, |
273 | { SUB_CHIP_ID2, TWL6030_BASEADD_ZERO }, | ||
274 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
275 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
276 | { SUB_CHIP_ID2, TWL6030_BASEADD_RSV }, | ||
277 | |||
278 | { SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER }, | ||
279 | { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC }, | ||
280 | { SUB_CHIP_ID0, TWL6030_BASEADD_RTC }, | ||
281 | { SUB_CHIP_ID0, TWL6030_BASEADD_MEM }, | ||
282 | { SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER }, | ||
283 | }; | 255 | }; |
284 | 256 | ||
285 | static struct regmap_config twl6030_regmap_config[3] = { | 257 | static struct regmap_config twl6030_regmap_config[3] = { |
@@ -305,8 +277,30 @@ static struct regmap_config twl6030_regmap_config[3] = { | |||
305 | 277 | ||
306 | /*----------------------------------------------------------------------*/ | 278 | /*----------------------------------------------------------------------*/ |
307 | 279 | ||
280 | static inline int twl_get_num_slaves(void) | ||
281 | { | ||
282 | if (twl_class_is_4030()) | ||
283 | return 4; /* TWL4030 class have four slave address */ | ||
284 | else | ||
285 | return 3; /* TWL6030 class have three slave address */ | ||
286 | } | ||
287 | |||
288 | static inline int twl_get_last_module(void) | ||
289 | { | ||
290 | if (twl_class_is_4030()) | ||
291 | return TWL4030_MODULE_LAST; | ||
292 | else | ||
293 | return TWL6030_MODULE_LAST; | ||
294 | } | ||
295 | |||
308 | /* Exported Functions */ | 296 | /* Exported Functions */ |
309 | 297 | ||
298 | unsigned int twl_rev(void) | ||
299 | { | ||
300 | return twl_priv ? twl_priv->twl_id : 0; | ||
301 | } | ||
302 | EXPORT_SYMBOL(twl_rev); | ||
303 | |||
310 | /** | 304 | /** |
311 | * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0 | 305 | * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0 |
312 | * @mod_no: module number | 306 | * @mod_no: module number |
@@ -314,9 +308,6 @@ static struct regmap_config twl6030_regmap_config[3] = { | |||
314 | * @reg: register address (just offset will do) | 308 | * @reg: register address (just offset will do) |
315 | * @num_bytes: number of bytes to transfer | 309 | * @num_bytes: number of bytes to transfer |
316 | * | 310 | * |
317 | * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and | ||
318 | * valid data starts at Offset 1. | ||
319 | * | ||
320 | * Returns the result of operation - 0 is success | 311 | * Returns the result of operation - 0 is success |
321 | */ | 312 | */ |
322 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | 313 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
@@ -325,24 +316,21 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
325 | int sid; | 316 | int sid; |
326 | struct twl_client *twl; | 317 | struct twl_client *twl; |
327 | 318 | ||
328 | if (unlikely(mod_no >= TWL_MODULE_LAST)) { | 319 | if (unlikely(!twl_priv || !twl_priv->ready)) { |
329 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | ||
330 | return -EPERM; | ||
331 | } | ||
332 | if (unlikely(!inuse)) { | ||
333 | pr_err("%s: not initialized\n", DRIVER_NAME); | 320 | pr_err("%s: not initialized\n", DRIVER_NAME); |
334 | return -EPERM; | 321 | return -EPERM; |
335 | } | 322 | } |
336 | sid = twl_map[mod_no].sid; | 323 | if (unlikely(mod_no >= twl_get_last_module())) { |
337 | if (unlikely(sid == SUB_CHIP_ID_INVAL)) { | 324 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
338 | pr_err("%s: module %d is not part of the pmic\n", | 325 | return -EPERM; |
339 | DRIVER_NAME, mod_no); | ||
340 | return -EINVAL; | ||
341 | } | 326 | } |
342 | twl = &twl_modules[sid]; | ||
343 | 327 | ||
344 | ret = regmap_bulk_write(twl->regmap, twl_map[mod_no].base + reg, | 328 | sid = twl_priv->twl_map[mod_no].sid; |
345 | value, num_bytes); | 329 | twl = &twl_priv->twl_modules[sid]; |
330 | |||
331 | ret = regmap_bulk_write(twl->regmap, | ||
332 | twl_priv->twl_map[mod_no].base + reg, value, | ||
333 | num_bytes); | ||
346 | 334 | ||
347 | if (ret) | 335 | if (ret) |
348 | pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n", | 336 | pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n", |
@@ -367,24 +355,21 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
367 | int sid; | 355 | int sid; |
368 | struct twl_client *twl; | 356 | struct twl_client *twl; |
369 | 357 | ||
370 | if (unlikely(mod_no >= TWL_MODULE_LAST)) { | 358 | if (unlikely(!twl_priv || !twl_priv->ready)) { |
371 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | ||
372 | return -EPERM; | ||
373 | } | ||
374 | if (unlikely(!inuse)) { | ||
375 | pr_err("%s: not initialized\n", DRIVER_NAME); | 359 | pr_err("%s: not initialized\n", DRIVER_NAME); |
376 | return -EPERM; | 360 | return -EPERM; |
377 | } | 361 | } |
378 | sid = twl_map[mod_no].sid; | 362 | if (unlikely(mod_no >= twl_get_last_module())) { |
379 | if (unlikely(sid == SUB_CHIP_ID_INVAL)) { | 363 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
380 | pr_err("%s: module %d is not part of the pmic\n", | 364 | return -EPERM; |
381 | DRIVER_NAME, mod_no); | ||
382 | return -EINVAL; | ||
383 | } | 365 | } |
384 | twl = &twl_modules[sid]; | ||
385 | 366 | ||
386 | ret = regmap_bulk_read(twl->regmap, twl_map[mod_no].base + reg, | 367 | sid = twl_priv->twl_map[mod_no].sid; |
387 | value, num_bytes); | 368 | twl = &twl_priv->twl_modules[sid]; |
369 | |||
370 | ret = regmap_bulk_read(twl->regmap, | ||
371 | twl_priv->twl_map[mod_no].base + reg, value, | ||
372 | num_bytes); | ||
388 | 373 | ||
389 | if (ret) | 374 | if (ret) |
390 | pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n", | 375 | pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n", |
@@ -394,34 +379,6 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
394 | } | 379 | } |
395 | EXPORT_SYMBOL(twl_i2c_read); | 380 | EXPORT_SYMBOL(twl_i2c_read); |
396 | 381 | ||
397 | /** | ||
398 | * twl_i2c_write_u8 - Writes a 8 bit register in TWL4030/TWL5030/TWL60X0 | ||
399 | * @mod_no: module number | ||
400 | * @value: the value to be written 8 bit | ||
401 | * @reg: register address (just offset will do) | ||
402 | * | ||
403 | * Returns result of operation - 0 is success | ||
404 | */ | ||
405 | int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg) | ||
406 | { | ||
407 | return twl_i2c_write(mod_no, &value, reg, 1); | ||
408 | } | ||
409 | EXPORT_SYMBOL(twl_i2c_write_u8); | ||
410 | |||
411 | /** | ||
412 | * twl_i2c_read_u8 - Reads a 8 bit register from TWL4030/TWL5030/TWL60X0 | ||
413 | * @mod_no: module number | ||
414 | * @value: the value read 8 bit | ||
415 | * @reg: register address (just offset will do) | ||
416 | * | ||
417 | * Returns result of operation - 0 is success | ||
418 | */ | ||
419 | int twl_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) | ||
420 | { | ||
421 | return twl_i2c_read(mod_no, value, reg, 1); | ||
422 | } | ||
423 | EXPORT_SYMBOL(twl_i2c_read_u8); | ||
424 | |||
425 | /*----------------------------------------------------------------------*/ | 382 | /*----------------------------------------------------------------------*/ |
426 | 383 | ||
427 | /** | 384 | /** |
@@ -440,7 +397,7 @@ static int twl_read_idcode_register(void) | |||
440 | goto fail; | 397 | goto fail; |
441 | } | 398 | } |
442 | 399 | ||
443 | err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode), | 400 | err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_priv->twl_idcode), |
444 | REG_IDCODE_7_0, 4); | 401 | REG_IDCODE_7_0, 4); |
445 | if (err) { | 402 | if (err) { |
446 | pr_err("TWL4030: unable to read IDCODE -%d\n", err); | 403 | pr_err("TWL4030: unable to read IDCODE -%d\n", err); |
@@ -461,7 +418,7 @@ fail: | |||
461 | */ | 418 | */ |
462 | int twl_get_type(void) | 419 | int twl_get_type(void) |
463 | { | 420 | { |
464 | return TWL_SIL_TYPE(twl_idcode); | 421 | return TWL_SIL_TYPE(twl_priv->twl_idcode); |
465 | } | 422 | } |
466 | EXPORT_SYMBOL_GPL(twl_get_type); | 423 | EXPORT_SYMBOL_GPL(twl_get_type); |
467 | 424 | ||
@@ -472,7 +429,7 @@ EXPORT_SYMBOL_GPL(twl_get_type); | |||
472 | */ | 429 | */ |
473 | int twl_get_version(void) | 430 | int twl_get_version(void) |
474 | { | 431 | { |
475 | return TWL_SIL_REV(twl_idcode); | 432 | return TWL_SIL_REV(twl_priv->twl_idcode); |
476 | } | 433 | } |
477 | EXPORT_SYMBOL_GPL(twl_get_version); | 434 | EXPORT_SYMBOL_GPL(twl_get_version); |
478 | 435 | ||
@@ -509,13 +466,20 @@ int twl_get_hfclk_rate(void) | |||
509 | EXPORT_SYMBOL_GPL(twl_get_hfclk_rate); | 466 | EXPORT_SYMBOL_GPL(twl_get_hfclk_rate); |
510 | 467 | ||
511 | static struct device * | 468 | static struct device * |
512 | add_numbered_child(unsigned chip, const char *name, int num, | 469 | add_numbered_child(unsigned mod_no, const char *name, int num, |
513 | void *pdata, unsigned pdata_len, | 470 | void *pdata, unsigned pdata_len, |
514 | bool can_wakeup, int irq0, int irq1) | 471 | bool can_wakeup, int irq0, int irq1) |
515 | { | 472 | { |
516 | struct platform_device *pdev; | 473 | struct platform_device *pdev; |
517 | struct twl_client *twl = &twl_modules[chip]; | 474 | struct twl_client *twl; |
518 | int status; | 475 | int status, sid; |
476 | |||
477 | if (unlikely(mod_no >= twl_get_last_module())) { | ||
478 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | ||
479 | return ERR_PTR(-EPERM); | ||
480 | } | ||
481 | sid = twl_priv->twl_map[mod_no].sid; | ||
482 | twl = &twl_priv->twl_modules[sid]; | ||
519 | 483 | ||
520 | pdev = platform_device_alloc(name, num); | 484 | pdev = platform_device_alloc(name, num); |
521 | if (!pdev) { | 485 | if (!pdev) { |
@@ -560,11 +524,11 @@ err: | |||
560 | return &pdev->dev; | 524 | return &pdev->dev; |
561 | } | 525 | } |
562 | 526 | ||
563 | static inline struct device *add_child(unsigned chip, const char *name, | 527 | static inline struct device *add_child(unsigned mod_no, const char *name, |
564 | void *pdata, unsigned pdata_len, | 528 | void *pdata, unsigned pdata_len, |
565 | bool can_wakeup, int irq0, int irq1) | 529 | bool can_wakeup, int irq0, int irq1) |
566 | { | 530 | { |
567 | return add_numbered_child(chip, name, -1, pdata, pdata_len, | 531 | return add_numbered_child(mod_no, name, -1, pdata, pdata_len, |
568 | can_wakeup, irq0, irq1); | 532 | can_wakeup, irq0, irq1); |
569 | } | 533 | } |
570 | 534 | ||
@@ -573,7 +537,6 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
573 | struct regulator_consumer_supply *consumers, | 537 | struct regulator_consumer_supply *consumers, |
574 | unsigned num_consumers, unsigned long features) | 538 | unsigned num_consumers, unsigned long features) |
575 | { | 539 | { |
576 | unsigned sub_chip_id; | ||
577 | struct twl_regulator_driver_data drv_data; | 540 | struct twl_regulator_driver_data drv_data; |
578 | 541 | ||
579 | /* regulator framework demands init_data ... */ | 542 | /* regulator framework demands init_data ... */ |
@@ -600,8 +563,7 @@ add_regulator_linked(int num, struct regulator_init_data *pdata, | |||
600 | } | 563 | } |
601 | 564 | ||
602 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ | 565 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ |
603 | sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid; | 566 | return add_numbered_child(TWL_MODULE_PM_MASTER, "twl_reg", num, |
604 | return add_numbered_child(sub_chip_id, "twl_reg", num, | ||
605 | pdata, sizeof(*pdata), false, 0, 0); | 567 | pdata, sizeof(*pdata), false, 0, 0); |
606 | } | 568 | } |
607 | 569 | ||
@@ -623,10 +585,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
623 | unsigned long features) | 585 | unsigned long features) |
624 | { | 586 | { |
625 | struct device *child; | 587 | struct device *child; |
626 | unsigned sub_chip_id; | ||
627 | 588 | ||
628 | if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) { | 589 | if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) { |
629 | child = add_child(SUB_CHIP_ID1, "twl4030_gpio", | 590 | child = add_child(TWL4030_MODULE_GPIO, "twl4030_gpio", |
630 | pdata->gpio, sizeof(*pdata->gpio), | 591 | pdata->gpio, sizeof(*pdata->gpio), |
631 | false, irq_base + GPIO_INTR_OFFSET, 0); | 592 | false, irq_base + GPIO_INTR_OFFSET, 0); |
632 | if (IS_ERR(child)) | 593 | if (IS_ERR(child)) |
@@ -634,7 +595,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
634 | } | 595 | } |
635 | 596 | ||
636 | if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) { | 597 | if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) { |
637 | child = add_child(SUB_CHIP_ID2, "twl4030_keypad", | 598 | child = add_child(TWL4030_MODULE_KEYPAD, "twl4030_keypad", |
638 | pdata->keypad, sizeof(*pdata->keypad), | 599 | pdata->keypad, sizeof(*pdata->keypad), |
639 | true, irq_base + KEYPAD_INTR_OFFSET, 0); | 600 | true, irq_base + KEYPAD_INTR_OFFSET, 0); |
640 | if (IS_ERR(child)) | 601 | if (IS_ERR(child)) |
@@ -643,7 +604,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
643 | 604 | ||
644 | if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc && | 605 | if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc && |
645 | twl_class_is_4030()) { | 606 | twl_class_is_4030()) { |
646 | child = add_child(SUB_CHIP_ID2, "twl4030_madc", | 607 | child = add_child(TWL4030_MODULE_MADC, "twl4030_madc", |
647 | pdata->madc, sizeof(*pdata->madc), | 608 | pdata->madc, sizeof(*pdata->madc), |
648 | true, irq_base + MADC_INTR_OFFSET, 0); | 609 | true, irq_base + MADC_INTR_OFFSET, 0); |
649 | if (IS_ERR(child)) | 610 | if (IS_ERR(child)) |
@@ -658,22 +619,21 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
658 | * Eventually, Linux might become more aware of such | 619 | * Eventually, Linux might become more aware of such |
659 | * HW security concerns, and "least privilege". | 620 | * HW security concerns, and "least privilege". |
660 | */ | 621 | */ |
661 | sub_chip_id = twl_map[TWL_MODULE_RTC].sid; | 622 | child = add_child(TWL_MODULE_RTC, "twl_rtc", NULL, 0, |
662 | child = add_child(sub_chip_id, "twl_rtc", NULL, 0, | ||
663 | true, irq_base + RTC_INTR_OFFSET, 0); | 623 | true, irq_base + RTC_INTR_OFFSET, 0); |
664 | if (IS_ERR(child)) | 624 | if (IS_ERR(child)) |
665 | return PTR_ERR(child); | 625 | return PTR_ERR(child); |
666 | } | 626 | } |
667 | 627 | ||
668 | if (IS_ENABLED(CONFIG_PWM_TWL)) { | 628 | if (IS_ENABLED(CONFIG_PWM_TWL)) { |
669 | child = add_child(SUB_CHIP_ID1, "twl-pwm", NULL, 0, | 629 | child = add_child(TWL_MODULE_PWM, "twl-pwm", NULL, 0, |
670 | false, 0, 0); | 630 | false, 0, 0); |
671 | if (IS_ERR(child)) | 631 | if (IS_ERR(child)) |
672 | return PTR_ERR(child); | 632 | return PTR_ERR(child); |
673 | } | 633 | } |
674 | 634 | ||
675 | if (IS_ENABLED(CONFIG_PWM_TWL_LED)) { | 635 | if (IS_ENABLED(CONFIG_PWM_TWL_LED)) { |
676 | child = add_child(SUB_CHIP_ID1, "twl-pwmled", NULL, 0, | 636 | child = add_child(TWL_MODULE_LED, "twl-pwmled", NULL, 0, |
677 | false, 0, 0); | 637 | false, 0, 0); |
678 | if (IS_ERR(child)) | 638 | if (IS_ERR(child)) |
679 | return PTR_ERR(child); | 639 | return PTR_ERR(child); |
@@ -725,7 +685,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
725 | 685 | ||
726 | } | 686 | } |
727 | 687 | ||
728 | child = add_child(SUB_CHIP_ID0, "twl4030_usb", | 688 | child = add_child(TWL_MODULE_USB, "twl4030_usb", |
729 | pdata->usb, sizeof(*pdata->usb), true, | 689 | pdata->usb, sizeof(*pdata->usb), true, |
730 | /* irq0 = USB_PRES, irq1 = USB */ | 690 | /* irq0 = USB_PRES, irq1 = USB */ |
731 | irq_base + USB_PRES_INTR_OFFSET, | 691 | irq_base + USB_PRES_INTR_OFFSET, |
@@ -774,7 +734,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
774 | 734 | ||
775 | pdata->usb->features = features; | 735 | pdata->usb->features = features; |
776 | 736 | ||
777 | child = add_child(SUB_CHIP_ID0, "twl6030_usb", | 737 | child = add_child(TWL_MODULE_USB, "twl6030_usb", |
778 | pdata->usb, sizeof(*pdata->usb), true, | 738 | pdata->usb, sizeof(*pdata->usb), true, |
779 | /* irq1 = VBUS_PRES, irq0 = USB ID */ | 739 | /* irq1 = VBUS_PRES, irq0 = USB ID */ |
780 | irq_base + USBOTG_INTR_OFFSET, | 740 | irq_base + USBOTG_INTR_OFFSET, |
@@ -799,22 +759,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
799 | } | 759 | } |
800 | 760 | ||
801 | if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) { | 761 | if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) { |
802 | child = add_child(SUB_CHIP_ID3, "twl4030_wdt", NULL, 0, | 762 | child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL, |
803 | false, 0, 0); | 763 | 0, false, 0, 0); |
804 | if (IS_ERR(child)) | 764 | if (IS_ERR(child)) |
805 | return PTR_ERR(child); | 765 | return PTR_ERR(child); |
806 | } | 766 | } |
807 | 767 | ||
808 | if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) { | 768 | if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) { |
809 | child = add_child(SUB_CHIP_ID3, "twl4030_pwrbutton", NULL, 0, | 769 | child = add_child(TWL_MODULE_PM_MASTER, "twl4030_pwrbutton", |
810 | true, irq_base + 8 + 0, 0); | 770 | NULL, 0, true, irq_base + 8 + 0, 0); |
811 | if (IS_ERR(child)) | 771 | if (IS_ERR(child)) |
812 | return PTR_ERR(child); | 772 | return PTR_ERR(child); |
813 | } | 773 | } |
814 | 774 | ||
815 | if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio && | 775 | if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio && |
816 | twl_class_is_4030()) { | 776 | twl_class_is_4030()) { |
817 | child = add_child(SUB_CHIP_ID1, "twl4030-audio", | 777 | child = add_child(TWL4030_MODULE_AUDIO_VOICE, "twl4030-audio", |
818 | pdata->audio, sizeof(*pdata->audio), | 778 | pdata->audio, sizeof(*pdata->audio), |
819 | false, 0, 0); | 779 | false, 0, 0); |
820 | if (IS_ERR(child)) | 780 | if (IS_ERR(child)) |
@@ -1054,7 +1014,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | |||
1054 | 1014 | ||
1055 | if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci && | 1015 | if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci && |
1056 | !(features & (TPS_SUBSET | TWL5031))) { | 1016 | !(features & (TPS_SUBSET | TWL5031))) { |
1057 | child = add_child(SUB_CHIP_ID3, "twl4030_bci", | 1017 | child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci", |
1058 | pdata->bci, sizeof(*pdata->bci), false, | 1018 | pdata->bci, sizeof(*pdata->bci), false, |
1059 | /* irq0 = CHG_PRES, irq1 = BCI */ | 1019 | /* irq0 = CHG_PRES, irq1 = BCI */ |
1060 | irq_base + BCI_PRES_INTR_OFFSET, | 1020 | irq_base + BCI_PRES_INTR_OFFSET, |
@@ -1145,25 +1105,23 @@ static int twl_remove(struct i2c_client *client) | |||
1145 | unsigned i, num_slaves; | 1105 | unsigned i, num_slaves; |
1146 | int status; | 1106 | int status; |
1147 | 1107 | ||
1148 | if (twl_class_is_4030()) { | 1108 | if (twl_class_is_4030()) |
1149 | status = twl4030_exit_irq(); | 1109 | status = twl4030_exit_irq(); |
1150 | num_slaves = TWL_NUM_SLAVES; | 1110 | else |
1151 | } else { | ||
1152 | status = twl6030_exit_irq(); | 1111 | status = twl6030_exit_irq(); |
1153 | num_slaves = TWL_NUM_SLAVES - 1; | ||
1154 | } | ||
1155 | 1112 | ||
1156 | if (status < 0) | 1113 | if (status < 0) |
1157 | return status; | 1114 | return status; |
1158 | 1115 | ||
1116 | num_slaves = twl_get_num_slaves(); | ||
1159 | for (i = 0; i < num_slaves; i++) { | 1117 | for (i = 0; i < num_slaves; i++) { |
1160 | struct twl_client *twl = &twl_modules[i]; | 1118 | struct twl_client *twl = &twl_priv->twl_modules[i]; |
1161 | 1119 | ||
1162 | if (twl->client && twl->client != client) | 1120 | if (twl->client && twl->client != client) |
1163 | i2c_unregister_device(twl->client); | 1121 | i2c_unregister_device(twl->client); |
1164 | twl_modules[i].client = NULL; | 1122 | twl->client = NULL; |
1165 | } | 1123 | } |
1166 | inuse = false; | 1124 | twl_priv->ready = false; |
1167 | return 0; | 1125 | return 0; |
1168 | } | 1126 | } |
1169 | 1127 | ||
@@ -1179,6 +1137,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1179 | int status; | 1137 | int status; |
1180 | unsigned i, num_slaves; | 1138 | unsigned i, num_slaves; |
1181 | 1139 | ||
1140 | if (!node && !pdata) { | ||
1141 | dev_err(&client->dev, "no platform data\n"); | ||
1142 | return -EINVAL; | ||
1143 | } | ||
1144 | |||
1145 | if (twl_priv) { | ||
1146 | dev_dbg(&client->dev, "only one instance of %s allowed\n", | ||
1147 | DRIVER_NAME); | ||
1148 | return -EBUSY; | ||
1149 | } | ||
1150 | |||
1182 | pdev = platform_device_alloc(DRIVER_NAME, -1); | 1151 | pdev = platform_device_alloc(DRIVER_NAME, -1); |
1183 | if (!pdev) { | 1152 | if (!pdev) { |
1184 | dev_err(&client->dev, "can't alloc pdev\n"); | 1153 | dev_err(&client->dev, "can't alloc pdev\n"); |
@@ -1191,54 +1160,44 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1191 | return status; | 1160 | return status; |
1192 | } | 1161 | } |
1193 | 1162 | ||
1194 | if (node && !pdata) { | ||
1195 | /* | ||
1196 | * XXX: Temporary pdata until the information is correctly | ||
1197 | * retrieved by every TWL modules from DT. | ||
1198 | */ | ||
1199 | pdata = devm_kzalloc(&client->dev, | ||
1200 | sizeof(struct twl4030_platform_data), | ||
1201 | GFP_KERNEL); | ||
1202 | if (!pdata) { | ||
1203 | status = -ENOMEM; | ||
1204 | goto free; | ||
1205 | } | ||
1206 | } | ||
1207 | |||
1208 | if (!pdata) { | ||
1209 | dev_dbg(&client->dev, "no platform data?\n"); | ||
1210 | status = -EINVAL; | ||
1211 | goto free; | ||
1212 | } | ||
1213 | |||
1214 | platform_set_drvdata(pdev, pdata); | ||
1215 | |||
1216 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { | 1163 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { |
1217 | dev_dbg(&client->dev, "can't talk I2C?\n"); | 1164 | dev_dbg(&client->dev, "can't talk I2C?\n"); |
1218 | status = -EIO; | 1165 | status = -EIO; |
1219 | goto free; | 1166 | goto free; |
1220 | } | 1167 | } |
1221 | 1168 | ||
1222 | if (inuse) { | 1169 | twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private), |
1223 | dev_dbg(&client->dev, "driver is already in use\n"); | 1170 | GFP_KERNEL); |
1224 | status = -EBUSY; | 1171 | if (!twl_priv) { |
1172 | status = -ENOMEM; | ||
1225 | goto free; | 1173 | goto free; |
1226 | } | 1174 | } |
1227 | 1175 | ||
1228 | if ((id->driver_data) & TWL6030_CLASS) { | 1176 | if ((id->driver_data) & TWL6030_CLASS) { |
1229 | twl_id = TWL6030_CLASS_ID; | 1177 | twl_priv->twl_id = TWL6030_CLASS_ID; |
1230 | twl_map = &twl6030_map[0]; | 1178 | twl_priv->twl_map = &twl6030_map[0]; |
1179 | /* The charger base address is different in twl6025 */ | ||
1180 | if ((id->driver_data) & TWL6025_SUBCLASS) | ||
1181 | twl_priv->twl_map[TWL_MODULE_MAIN_CHARGE].base = | ||
1182 | TWL6025_BASEADD_CHARGER; | ||
1231 | twl_regmap_config = twl6030_regmap_config; | 1183 | twl_regmap_config = twl6030_regmap_config; |
1232 | num_slaves = TWL_NUM_SLAVES - 1; | ||
1233 | } else { | 1184 | } else { |
1234 | twl_id = TWL4030_CLASS_ID; | 1185 | twl_priv->twl_id = TWL4030_CLASS_ID; |
1235 | twl_map = &twl4030_map[0]; | 1186 | twl_priv->twl_map = &twl4030_map[0]; |
1236 | twl_regmap_config = twl4030_regmap_config; | 1187 | twl_regmap_config = twl4030_regmap_config; |
1237 | num_slaves = TWL_NUM_SLAVES; | 1188 | } |
1189 | |||
1190 | num_slaves = twl_get_num_slaves(); | ||
1191 | twl_priv->twl_modules = devm_kzalloc(&client->dev, | ||
1192 | sizeof(struct twl_client) * num_slaves, | ||
1193 | GFP_KERNEL); | ||
1194 | if (!twl_priv->twl_modules) { | ||
1195 | status = -ENOMEM; | ||
1196 | goto free; | ||
1238 | } | 1197 | } |
1239 | 1198 | ||
1240 | for (i = 0; i < num_slaves; i++) { | 1199 | for (i = 0; i < num_slaves; i++) { |
1241 | struct twl_client *twl = &twl_modules[i]; | 1200 | struct twl_client *twl = &twl_priv->twl_modules[i]; |
1242 | 1201 | ||
1243 | if (i == 0) { | 1202 | if (i == 0) { |
1244 | twl->client = client; | 1203 | twl->client = client; |
@@ -1264,19 +1223,19 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1264 | } | 1223 | } |
1265 | } | 1224 | } |
1266 | 1225 | ||
1267 | inuse = true; | 1226 | twl_priv->ready = true; |
1268 | 1227 | ||
1269 | /* setup clock framework */ | 1228 | /* setup clock framework */ |
1270 | clocks_init(&pdev->dev, pdata->clock); | 1229 | clocks_init(&pdev->dev, pdata ? pdata->clock : NULL); |
1271 | 1230 | ||
1272 | /* read TWL IDCODE Register */ | 1231 | /* read TWL IDCODE Register */ |
1273 | if (twl_id == TWL4030_CLASS_ID) { | 1232 | if (twl_class_is_4030()) { |
1274 | status = twl_read_idcode_register(); | 1233 | status = twl_read_idcode_register(); |
1275 | WARN(status < 0, "Error: reading twl_idcode register value\n"); | 1234 | WARN(status < 0, "Error: reading twl_idcode register value\n"); |
1276 | } | 1235 | } |
1277 | 1236 | ||
1278 | /* load power event scripts */ | 1237 | /* load power event scripts */ |
1279 | if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) | 1238 | if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata && pdata->power) |
1280 | twl4030_power_init(pdata->power); | 1239 | twl4030_power_init(pdata->power); |
1281 | 1240 | ||
1282 | /* Maybe init the T2 Interrupt subsystem */ | 1241 | /* Maybe init the T2 Interrupt subsystem */ |
@@ -1308,10 +1267,9 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1308 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); | 1267 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); |
1309 | } | 1268 | } |
1310 | 1269 | ||
1311 | status = -ENODEV; | ||
1312 | if (node) | 1270 | if (node) |
1313 | status = of_platform_populate(node, NULL, NULL, &client->dev); | 1271 | status = of_platform_populate(node, NULL, NULL, &client->dev); |
1314 | if (status) | 1272 | else |
1315 | status = add_children(pdata, irq_base, id->driver_data); | 1273 | status = add_children(pdata, irq_base, id->driver_data); |
1316 | 1274 | ||
1317 | fail: | 1275 | fail: |
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 558c2928f261..bf75e967a1f3 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c | |||
@@ -49,6 +49,8 @@ | |||
49 | #define SYS_ID_HBI_SHIFT 16 | 49 | #define SYS_ID_HBI_SHIFT 16 |
50 | #define SYS_PROCIDx_HBI_SHIFT 0 | 50 | #define SYS_PROCIDx_HBI_SHIFT 0 |
51 | 51 | ||
52 | #define SYS_LED_LED(n) (1 << (n)) | ||
53 | |||
52 | #define SYS_MCI_CARDIN (1 << 0) | 54 | #define SYS_MCI_CARDIN (1 << 0) |
53 | #define SYS_MCI_WPROT (1 << 1) | 55 | #define SYS_MCI_WPROT (1 << 1) |
54 | 56 | ||
@@ -336,34 +338,40 @@ void __init vexpress_sysreg_early_init(void __iomem *base) | |||
336 | 338 | ||
337 | void __init vexpress_sysreg_of_early_init(void) | 339 | void __init vexpress_sysreg_of_early_init(void) |
338 | { | 340 | { |
339 | struct device_node *node = of_find_compatible_node(NULL, NULL, | 341 | struct device_node *node; |
340 | "arm,vexpress-sysreg"); | 342 | |
343 | if (vexpress_sysreg_base) | ||
344 | return; | ||
341 | 345 | ||
346 | node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg"); | ||
342 | if (node) { | 347 | if (node) { |
343 | vexpress_sysreg_base = of_iomap(node, 0); | 348 | vexpress_sysreg_base = of_iomap(node, 0); |
344 | vexpress_sysreg_setup(node); | 349 | vexpress_sysreg_setup(node); |
345 | } else { | ||
346 | pr_info("vexpress-sysreg: No Device Tree node found."); | ||
347 | } | 350 | } |
348 | } | 351 | } |
349 | 352 | ||
350 | 353 | ||
354 | #define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \ | ||
355 | [VEXPRESS_GPIO_##_name] = { \ | ||
356 | .reg = _reg, \ | ||
357 | .value = _reg##_##_value, \ | ||
358 | } | ||
359 | |||
351 | static struct vexpress_sysreg_gpio { | 360 | static struct vexpress_sysreg_gpio { |
352 | unsigned long reg; | 361 | unsigned long reg; |
353 | u32 value; | 362 | u32 value; |
354 | } vexpress_sysreg_gpios[] = { | 363 | } vexpress_sysreg_gpios[] = { |
355 | [VEXPRESS_GPIO_MMC_CARDIN] = { | 364 | VEXPRESS_SYSREG_GPIO(MMC_CARDIN, SYS_MCI, CARDIN), |
356 | .reg = SYS_MCI, | 365 | VEXPRESS_SYSREG_GPIO(MMC_WPROT, SYS_MCI, WPROT), |
357 | .value = SYS_MCI_CARDIN, | 366 | VEXPRESS_SYSREG_GPIO(FLASH_WPn, SYS_FLASH, WPn), |
358 | }, | 367 | VEXPRESS_SYSREG_GPIO(LED0, SYS_LED, LED(0)), |
359 | [VEXPRESS_GPIO_MMC_WPROT] = { | 368 | VEXPRESS_SYSREG_GPIO(LED1, SYS_LED, LED(1)), |
360 | .reg = SYS_MCI, | 369 | VEXPRESS_SYSREG_GPIO(LED2, SYS_LED, LED(2)), |
361 | .value = SYS_MCI_WPROT, | 370 | VEXPRESS_SYSREG_GPIO(LED3, SYS_LED, LED(3)), |
362 | }, | 371 | VEXPRESS_SYSREG_GPIO(LED4, SYS_LED, LED(4)), |
363 | [VEXPRESS_GPIO_FLASH_WPn] = { | 372 | VEXPRESS_SYSREG_GPIO(LED5, SYS_LED, LED(5)), |
364 | .reg = SYS_FLASH, | 373 | VEXPRESS_SYSREG_GPIO(LED6, SYS_LED, LED(6)), |
365 | .value = SYS_FLASH_WPn, | 374 | VEXPRESS_SYSREG_GPIO(LED7, SYS_LED, LED(7)), |
366 | }, | ||
367 | }; | 375 | }; |
368 | 376 | ||
369 | static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip, | 377 | static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip, |
@@ -372,12 +380,6 @@ static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip, | |||
372 | return 0; | 380 | return 0; |
373 | } | 381 | } |
374 | 382 | ||
375 | static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip, | ||
376 | unsigned offset, int value) | ||
377 | { | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int vexpress_sysreg_gpio_get(struct gpio_chip *chip, | 383 | static int vexpress_sysreg_gpio_get(struct gpio_chip *chip, |
382 | unsigned offset) | 384 | unsigned offset) |
383 | { | 385 | { |
@@ -401,6 +403,14 @@ static void vexpress_sysreg_gpio_set(struct gpio_chip *chip, | |||
401 | writel(reg_value, vexpress_sysreg_base + gpio->reg); | 403 | writel(reg_value, vexpress_sysreg_base + gpio->reg); |
402 | } | 404 | } |
403 | 405 | ||
406 | static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip, | ||
407 | unsigned offset, int value) | ||
408 | { | ||
409 | vexpress_sysreg_gpio_set(chip, offset, value); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
404 | static struct gpio_chip vexpress_sysreg_gpio_chip = { | 414 | static struct gpio_chip vexpress_sysreg_gpio_chip = { |
405 | .label = "vexpress-sysreg", | 415 | .label = "vexpress-sysreg", |
406 | .direction_input = vexpress_sysreg_gpio_direction_input, | 416 | .direction_input = vexpress_sysreg_gpio_direction_input, |
@@ -412,6 +422,30 @@ static struct gpio_chip vexpress_sysreg_gpio_chip = { | |||
412 | }; | 422 | }; |
413 | 423 | ||
414 | 424 | ||
425 | #define VEXPRESS_SYSREG_GREEN_LED(_name, _default_trigger, _gpio) \ | ||
426 | { \ | ||
427 | .name = "v2m:green:"_name, \ | ||
428 | .default_trigger = _default_trigger, \ | ||
429 | .gpio = VEXPRESS_GPIO_##_gpio, \ | ||
430 | } | ||
431 | |||
432 | struct gpio_led vexpress_sysreg_leds[] = { | ||
433 | VEXPRESS_SYSREG_GREEN_LED("user1", "heartbeat", LED0), | ||
434 | VEXPRESS_SYSREG_GREEN_LED("user2", "mmc0", LED1), | ||
435 | VEXPRESS_SYSREG_GREEN_LED("user3", "cpu0", LED2), | ||
436 | VEXPRESS_SYSREG_GREEN_LED("user4", "cpu1", LED3), | ||
437 | VEXPRESS_SYSREG_GREEN_LED("user5", "cpu2", LED4), | ||
438 | VEXPRESS_SYSREG_GREEN_LED("user6", "cpu3", LED5), | ||
439 | VEXPRESS_SYSREG_GREEN_LED("user7", "cpu4", LED6), | ||
440 | VEXPRESS_SYSREG_GREEN_LED("user8", "cpu5", LED7), | ||
441 | }; | ||
442 | |||
443 | struct gpio_led_platform_data vexpress_sysreg_leds_pdata = { | ||
444 | .num_leds = ARRAY_SIZE(vexpress_sysreg_leds), | ||
445 | .leds = vexpress_sysreg_leds, | ||
446 | }; | ||
447 | |||
448 | |||
415 | static ssize_t vexpress_sysreg_sys_id_show(struct device *dev, | 449 | static ssize_t vexpress_sysreg_sys_id_show(struct device *dev, |
416 | struct device_attribute *attr, char *buf) | 450 | struct device_attribute *attr, char *buf) |
417 | { | 451 | { |
@@ -456,6 +490,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) | |||
456 | return err; | 490 | return err; |
457 | } | 491 | } |
458 | 492 | ||
493 | platform_device_register_data(vexpress_sysreg_dev, "leds-gpio", | ||
494 | PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata, | ||
495 | sizeof(vexpress_sysreg_leds_pdata)); | ||
496 | |||
459 | vexpress_sysreg_dev = &pdev->dev; | 497 | vexpress_sysreg_dev = &pdev->dev; |
460 | 498 | ||
461 | device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); | 499 | device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); |
@@ -478,6 +516,7 @@ static struct platform_driver vexpress_sysreg_driver = { | |||
478 | 516 | ||
479 | static int __init vexpress_sysreg_init(void) | 517 | static int __init vexpress_sysreg_init(void) |
480 | { | 518 | { |
519 | vexpress_sysreg_of_early_init(); | ||
481 | return platform_driver_register(&vexpress_sysreg_driver); | 520 | return platform_driver_register(&vexpress_sysreg_driver); |
482 | } | 521 | } |
483 | core_initcall(vexpress_sysreg_init); | 522 | core_initcall(vexpress_sysreg_init); |
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index a9d9d41d95d3..a433f580aa4c 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c | |||
@@ -59,12 +59,13 @@ static const struct reg_default wm5102_reva_patch[] = { | |||
59 | static const struct reg_default wm5102_revb_patch[] = { | 59 | static const struct reg_default wm5102_revb_patch[] = { |
60 | { 0x80, 0x0003 }, | 60 | { 0x80, 0x0003 }, |
61 | { 0x081, 0xE022 }, | 61 | { 0x081, 0xE022 }, |
62 | { 0x410, 0x6080 }, | 62 | { 0x410, 0x4080 }, |
63 | { 0x418, 0x6080 }, | 63 | { 0x418, 0x4080 }, |
64 | { 0x420, 0x6080 }, | 64 | { 0x420, 0x4080 }, |
65 | { 0x428, 0xC000 }, | 65 | { 0x428, 0xC000 }, |
66 | { 0x441, 0x8014 }, | 66 | { 0x4B0, 0x0066 }, |
67 | { 0x458, 0x000b }, | 67 | { 0x458, 0x000b }, |
68 | { 0x212, 0x0000 }, | ||
68 | { 0x80, 0x0000 }, | 69 | { 0x80, 0x0000 }, |
69 | }; | 70 | }; |
70 | 71 | ||
@@ -231,11 +232,9 @@ const struct regmap_irq_chip wm5102_irq = { | |||
231 | static const struct reg_default wm5102_reg_default[] = { | 232 | static const struct reg_default wm5102_reg_default[] = { |
232 | { 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */ | 233 | { 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */ |
233 | { 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */ | 234 | { 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */ |
234 | { 0x0000000D, 0x0000 }, /* R13 - Ctrl IF Status 1 */ | ||
235 | { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ | 235 | { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ |
236 | { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ | 236 | { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ |
237 | { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ | 237 | { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ |
238 | { 0x0000001A, 0x0000 }, /* R26 - Write Sequencer PROM */ | ||
239 | { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ | 238 | { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ |
240 | { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ | 239 | { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ |
241 | { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ | 240 | { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ |
@@ -250,12 +249,14 @@ static const struct reg_default wm5102_reg_default[] = { | |||
250 | { 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */ | 249 | { 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */ |
251 | { 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */ | 250 | { 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */ |
252 | { 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */ | 251 | { 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */ |
253 | { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 1 */ | 252 | { 0x00000066, 0x01FF }, /* R102 - Always On Triggers Sequence Select 1 */ |
254 | { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 2 */ | 253 | { 0x00000067, 0x01FF }, /* R103 - Always On Triggers Sequence Select 2 */ |
255 | { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 3 */ | 254 | { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 3 */ |
256 | { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 4 */ | 255 | { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */ |
257 | { 0x0000006C, 0x01FF }, /* R108 - Always On Triggers Sequence Select 5 */ | 256 | { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */ |
258 | { 0x0000006D, 0x01FF }, /* R109 - Always On Triggers Sequence Select 6 */ | 257 | { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */ |
258 | { 0x0000006E, 0x01FF }, /* R110 - Trigger Sequence Select 32 */ | ||
259 | { 0x0000006F, 0x01FF }, /* R111 - Trigger Sequence Select 33 */ | ||
259 | { 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */ | 260 | { 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */ |
260 | { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ | 261 | { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ |
261 | { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ | 262 | { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ |
@@ -265,13 +266,14 @@ static const struct reg_default wm5102_reg_default[] = { | |||
265 | { 0x00000095, 0x0000 }, /* R149 - Haptics phase 2 duration */ | 266 | { 0x00000095, 0x0000 }, /* R149 - Haptics phase 2 duration */ |
266 | { 0x00000096, 0x0000 }, /* R150 - Haptics phase 3 intensity */ | 267 | { 0x00000096, 0x0000 }, /* R150 - Haptics phase 3 intensity */ |
267 | { 0x00000097, 0x0000 }, /* R151 - Haptics phase 3 duration */ | 268 | { 0x00000097, 0x0000 }, /* R151 - Haptics phase 3 duration */ |
268 | { 0x00000100, 0x0001 }, /* R256 - Clock 32k 1 */ | 269 | { 0x00000100, 0x0002 }, /* R256 - Clock 32k 1 */ |
269 | { 0x00000101, 0x0304 }, /* R257 - System Clock 1 */ | 270 | { 0x00000101, 0x0304 }, /* R257 - System Clock 1 */ |
270 | { 0x00000102, 0x0011 }, /* R258 - Sample rate 1 */ | 271 | { 0x00000102, 0x0011 }, /* R258 - Sample rate 1 */ |
271 | { 0x00000103, 0x0011 }, /* R259 - Sample rate 2 */ | 272 | { 0x00000103, 0x0011 }, /* R259 - Sample rate 2 */ |
272 | { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */ | 273 | { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */ |
273 | { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */ | 274 | { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */ |
274 | { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */ | 275 | { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */ |
276 | { 0x00000114, 0x0011 }, /* R276 - Async sample rate 2 */ | ||
275 | { 0x00000149, 0x0000 }, /* R329 - Output system clock */ | 277 | { 0x00000149, 0x0000 }, /* R329 - Output system clock */ |
276 | { 0x0000014A, 0x0000 }, /* R330 - Output async clock */ | 278 | { 0x0000014A, 0x0000 }, /* R330 - Output async clock */ |
277 | { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */ | 279 | { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */ |
@@ -280,13 +282,14 @@ static const struct reg_default wm5102_reg_default[] = { | |||
280 | { 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */ | 282 | { 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */ |
281 | { 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */ | 283 | { 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */ |
282 | { 0x00000161, 0x0000 }, /* R353 - Dynamic Frequency Scaling 1 */ | 284 | { 0x00000161, 0x0000 }, /* R353 - Dynamic Frequency Scaling 1 */ |
283 | { 0x00000171, 0x0000 }, /* R369 - FLL1 Control 1 */ | 285 | { 0x00000171, 0x0002 }, /* R369 - FLL1 Control 1 */ |
284 | { 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */ | 286 | { 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */ |
285 | { 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */ | 287 | { 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */ |
286 | { 0x00000174, 0x007D }, /* R372 - FLL1 Control 4 */ | 288 | { 0x00000174, 0x007D }, /* R372 - FLL1 Control 4 */ |
287 | { 0x00000175, 0x0004 }, /* R373 - FLL1 Control 5 */ | 289 | { 0x00000175, 0x0004 }, /* R373 - FLL1 Control 5 */ |
288 | { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */ | 290 | { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */ |
289 | { 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */ | 291 | { 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */ |
292 | { 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */ | ||
290 | { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */ | 293 | { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */ |
291 | { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */ | 294 | { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */ |
292 | { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */ | 295 | { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */ |
@@ -302,6 +305,7 @@ static const struct reg_default wm5102_reg_default[] = { | |||
302 | { 0x00000195, 0x0004 }, /* R405 - FLL2 Control 5 */ | 305 | { 0x00000195, 0x0004 }, /* R405 - FLL2 Control 5 */ |
303 | { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */ | 306 | { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */ |
304 | { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */ | 307 | { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */ |
308 | { 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */ | ||
305 | { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */ | 309 | { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */ |
306 | { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */ | 310 | { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */ |
307 | { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */ | 311 | { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */ |
@@ -317,8 +321,12 @@ static const struct reg_default wm5102_reg_default[] = { | |||
317 | { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ | 321 | { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ |
318 | { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ | 322 | { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ |
319 | { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ | 323 | { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ |
324 | { 0x00000225, 0x0400 }, /* R549 - HP Ctrl 1L */ | ||
325 | { 0x00000226, 0x0400 }, /* R550 - HP Ctrl 1R */ | ||
320 | { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ | 326 | { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ |
321 | { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ | 327 | { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ |
328 | { 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */ | ||
329 | { 0x0000029F, 0x0000 }, /* R671 - Headphone Detect Test */ | ||
322 | { 0x000002A2, 0x0000 }, /* R674 - Micd clamp control */ | 330 | { 0x000002A2, 0x0000 }, /* R674 - Micd clamp control */ |
323 | { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ | 331 | { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ |
324 | { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ | 332 | { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ |
@@ -350,53 +358,44 @@ static const struct reg_default wm5102_reg_default[] = { | |||
350 | { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ | 358 | { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ |
351 | { 0x00000408, 0x0000 }, /* R1032 - Output Rate 1 */ | 359 | { 0x00000408, 0x0000 }, /* R1032 - Output Rate 1 */ |
352 | { 0x00000409, 0x0022 }, /* R1033 - Output Volume Ramp */ | 360 | { 0x00000409, 0x0022 }, /* R1033 - Output Volume Ramp */ |
353 | { 0x00000410, 0x0080 }, /* R1040 - Output Path Config 1L */ | 361 | { 0x00000410, 0x4080 }, /* R1040 - Output Path Config 1L */ |
354 | { 0x00000411, 0x0180 }, /* R1041 - DAC Digital Volume 1L */ | 362 | { 0x00000411, 0x0180 }, /* R1041 - DAC Digital Volume 1L */ |
355 | { 0x00000412, 0x0080 }, /* R1042 - DAC Volume Limit 1L */ | 363 | { 0x00000412, 0x0081 }, /* R1042 - DAC Volume Limit 1L */ |
356 | { 0x00000413, 0x0001 }, /* R1043 - Noise Gate Select 1L */ | 364 | { 0x00000413, 0x0001 }, /* R1043 - Noise Gate Select 1L */ |
357 | { 0x00000414, 0x0080 }, /* R1044 - Output Path Config 1R */ | 365 | { 0x00000414, 0x0080 }, /* R1044 - Output Path Config 1R */ |
358 | { 0x00000415, 0x0180 }, /* R1045 - DAC Digital Volume 1R */ | 366 | { 0x00000415, 0x0180 }, /* R1045 - DAC Digital Volume 1R */ |
359 | { 0x00000416, 0x0080 }, /* R1046 - DAC Volume Limit 1R */ | 367 | { 0x00000416, 0x0081 }, /* R1046 - DAC Volume Limit 1R */ |
360 | { 0x00000417, 0x0002 }, /* R1047 - Noise Gate Select 1R */ | 368 | { 0x00000417, 0x0002 }, /* R1047 - Noise Gate Select 1R */ |
361 | { 0x00000418, 0x0080 }, /* R1048 - Output Path Config 2L */ | 369 | { 0x00000418, 0x4080 }, /* R1048 - Output Path Config 2L */ |
362 | { 0x00000419, 0x0180 }, /* R1049 - DAC Digital Volume 2L */ | 370 | { 0x00000419, 0x0180 }, /* R1049 - DAC Digital Volume 2L */ |
363 | { 0x0000041A, 0x0080 }, /* R1050 - DAC Volume Limit 2L */ | 371 | { 0x0000041A, 0x0081 }, /* R1050 - DAC Volume Limit 2L */ |
364 | { 0x0000041B, 0x0004 }, /* R1051 - Noise Gate Select 2L */ | 372 | { 0x0000041B, 0x0004 }, /* R1051 - Noise Gate Select 2L */ |
365 | { 0x0000041C, 0x0080 }, /* R1052 - Output Path Config 2R */ | 373 | { 0x0000041C, 0x0080 }, /* R1052 - Output Path Config 2R */ |
366 | { 0x0000041D, 0x0180 }, /* R1053 - DAC Digital Volume 2R */ | 374 | { 0x0000041D, 0x0180 }, /* R1053 - DAC Digital Volume 2R */ |
367 | { 0x0000041E, 0x0080 }, /* R1054 - DAC Volume Limit 2R */ | 375 | { 0x0000041E, 0x0081 }, /* R1054 - DAC Volume Limit 2R */ |
368 | { 0x0000041F, 0x0008 }, /* R1055 - Noise Gate Select 2R */ | 376 | { 0x0000041F, 0x0008 }, /* R1055 - Noise Gate Select 2R */ |
369 | { 0x00000420, 0x0080 }, /* R1056 - Output Path Config 3L */ | 377 | { 0x00000420, 0x4080 }, /* R1056 - Output Path Config 3L */ |
370 | { 0x00000421, 0x0180 }, /* R1057 - DAC Digital Volume 3L */ | 378 | { 0x00000421, 0x0180 }, /* R1057 - DAC Digital Volume 3L */ |
371 | { 0x00000422, 0x0080 }, /* R1058 - DAC Volume Limit 3L */ | 379 | { 0x00000422, 0x0081 }, /* R1058 - DAC Volume Limit 3L */ |
372 | { 0x00000423, 0x0010 }, /* R1059 - Noise Gate Select 3L */ | 380 | { 0x00000423, 0x0010 }, /* R1059 - Noise Gate Select 3L */ |
373 | { 0x00000424, 0x0080 }, /* R1060 - Output Path Config 3R */ | 381 | { 0x00000428, 0xC000 }, /* R1064 - Output Path Config 4L */ |
374 | { 0x00000425, 0x0180 }, /* R1061 - DAC Digital Volume 3R */ | ||
375 | { 0x00000426, 0x0080 }, /* R1062 - DAC Volume Limit 3R */ | ||
376 | { 0x00000428, 0x0000 }, /* R1064 - Output Path Config 4L */ | ||
377 | { 0x00000429, 0x0180 }, /* R1065 - DAC Digital Volume 4L */ | 382 | { 0x00000429, 0x0180 }, /* R1065 - DAC Digital Volume 4L */ |
378 | { 0x0000042A, 0x0080 }, /* R1066 - Out Volume 4L */ | 383 | { 0x0000042A, 0x0081 }, /* R1066 - Out Volume 4L */ |
379 | { 0x0000042B, 0x0040 }, /* R1067 - Noise Gate Select 4L */ | 384 | { 0x0000042B, 0x0040 }, /* R1067 - Noise Gate Select 4L */ |
380 | { 0x0000042C, 0x0000 }, /* R1068 - Output Path Config 4R */ | ||
381 | { 0x0000042D, 0x0180 }, /* R1069 - DAC Digital Volume 4R */ | 385 | { 0x0000042D, 0x0180 }, /* R1069 - DAC Digital Volume 4R */ |
382 | { 0x0000042E, 0x0080 }, /* R1070 - Out Volume 4R */ | 386 | { 0x0000042E, 0x0081 }, /* R1070 - Out Volume 4R */ |
383 | { 0x0000042F, 0x0080 }, /* R1071 - Noise Gate Select 4R */ | 387 | { 0x0000042F, 0x0080 }, /* R1071 - Noise Gate Select 4R */ |
384 | { 0x00000430, 0x0000 }, /* R1072 - Output Path Config 5L */ | 388 | { 0x00000430, 0x0000 }, /* R1072 - Output Path Config 5L */ |
385 | { 0x00000431, 0x0180 }, /* R1073 - DAC Digital Volume 5L */ | 389 | { 0x00000431, 0x0180 }, /* R1073 - DAC Digital Volume 5L */ |
386 | { 0x00000432, 0x0080 }, /* R1074 - DAC Volume Limit 5L */ | 390 | { 0x00000432, 0x0081 }, /* R1074 - DAC Volume Limit 5L */ |
387 | { 0x00000433, 0x0100 }, /* R1075 - Noise Gate Select 5L */ | 391 | { 0x00000433, 0x0100 }, /* R1075 - Noise Gate Select 5L */ |
388 | { 0x00000434, 0x0000 }, /* R1076 - Output Path Config 5R */ | ||
389 | { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ | 392 | { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ |
390 | { 0x00000436, 0x0080 }, /* R1078 - DAC Volume Limit 5R */ | 393 | { 0x00000436, 0x0081 }, /* R1078 - DAC Volume Limit 5R */ |
391 | { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ | 394 | { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ |
392 | { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ | 395 | { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ |
393 | { 0x00000458, 0x0001 }, /* R1112 - Noise Gate Control */ | 396 | { 0x00000458, 0x0001 }, /* R1112 - Noise Gate Control */ |
394 | { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ | 397 | { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ |
395 | { 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */ | 398 | { 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */ |
396 | { 0x000004DC, 0x0000 }, /* R1244 - DAC comp 1 */ | ||
397 | { 0x000004DD, 0x0000 }, /* R1245 - DAC comp 2 */ | ||
398 | { 0x000004DE, 0x0000 }, /* R1246 - DAC comp 3 */ | ||
399 | { 0x000004DF, 0x0000 }, /* R1247 - DAC comp 4 */ | ||
400 | { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */ | 399 | { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */ |
401 | { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */ | 400 | { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */ |
402 | { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */ | 401 | { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */ |
@@ -424,7 +423,6 @@ static const struct reg_default wm5102_reg_default[] = { | |||
424 | { 0x00000518, 0x0007 }, /* R1304 - AIF1 Frame Ctrl 18 */ | 423 | { 0x00000518, 0x0007 }, /* R1304 - AIF1 Frame Ctrl 18 */ |
425 | { 0x00000519, 0x0000 }, /* R1305 - AIF1 Tx Enables */ | 424 | { 0x00000519, 0x0000 }, /* R1305 - AIF1 Tx Enables */ |
426 | { 0x0000051A, 0x0000 }, /* R1306 - AIF1 Rx Enables */ | 425 | { 0x0000051A, 0x0000 }, /* R1306 - AIF1 Rx Enables */ |
427 | { 0x0000051B, 0x0000 }, /* R1307 - AIF1 Force Write */ | ||
428 | { 0x00000540, 0x000C }, /* R1344 - AIF2 BCLK Ctrl */ | 426 | { 0x00000540, 0x000C }, /* R1344 - AIF2 BCLK Ctrl */ |
429 | { 0x00000541, 0x0008 }, /* R1345 - AIF2 Tx Pin Ctrl */ | 427 | { 0x00000541, 0x0008 }, /* R1345 - AIF2 Tx Pin Ctrl */ |
430 | { 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */ | 428 | { 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */ |
@@ -440,7 +438,6 @@ static const struct reg_default wm5102_reg_default[] = { | |||
440 | { 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */ | 438 | { 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */ |
441 | { 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */ | 439 | { 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */ |
442 | { 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */ | 440 | { 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */ |
443 | { 0x0000055B, 0x0000 }, /* R1371 - AIF2 Force Write */ | ||
444 | { 0x00000580, 0x000C }, /* R1408 - AIF3 BCLK Ctrl */ | 441 | { 0x00000580, 0x000C }, /* R1408 - AIF3 BCLK Ctrl */ |
445 | { 0x00000581, 0x0008 }, /* R1409 - AIF3 Tx Pin Ctrl */ | 442 | { 0x00000581, 0x0008 }, /* R1409 - AIF3 Tx Pin Ctrl */ |
446 | { 0x00000582, 0x0000 }, /* R1410 - AIF3 Rx Pin Ctrl */ | 443 | { 0x00000582, 0x0000 }, /* R1410 - AIF3 Rx Pin Ctrl */ |
@@ -456,7 +453,6 @@ static const struct reg_default wm5102_reg_default[] = { | |||
456 | { 0x00000592, 0x0001 }, /* R1426 - AIF3 Frame Ctrl 12 */ | 453 | { 0x00000592, 0x0001 }, /* R1426 - AIF3 Frame Ctrl 12 */ |
457 | { 0x00000599, 0x0000 }, /* R1433 - AIF3 Tx Enables */ | 454 | { 0x00000599, 0x0000 }, /* R1433 - AIF3 Tx Enables */ |
458 | { 0x0000059A, 0x0000 }, /* R1434 - AIF3 Rx Enables */ | 455 | { 0x0000059A, 0x0000 }, /* R1434 - AIF3 Rx Enables */ |
459 | { 0x0000059B, 0x0000 }, /* R1435 - AIF3 Force Write */ | ||
460 | { 0x000005E3, 0x0004 }, /* R1507 - SLIMbus Framer Ref Gear */ | 456 | { 0x000005E3, 0x0004 }, /* R1507 - SLIMbus Framer Ref Gear */ |
461 | { 0x000005E5, 0x0000 }, /* R1509 - SLIMbus Rates 1 */ | 457 | { 0x000005E5, 0x0000 }, /* R1509 - SLIMbus Rates 1 */ |
462 | { 0x000005E6, 0x0000 }, /* R1510 - SLIMbus Rates 2 */ | 458 | { 0x000005E6, 0x0000 }, /* R1510 - SLIMbus Rates 2 */ |
@@ -780,22 +776,6 @@ static const struct reg_default wm5102_reg_default[] = { | |||
780 | { 0x000008CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */ | 776 | { 0x000008CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */ |
781 | { 0x000008CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */ | 777 | { 0x000008CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */ |
782 | { 0x000008CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */ | 778 | { 0x000008CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */ |
783 | { 0x000008D0, 0x0000 }, /* R2256 - DRC2LMIX Input 1 Source */ | ||
784 | { 0x000008D1, 0x0080 }, /* R2257 - DRC2LMIX Input 1 Volume */ | ||
785 | { 0x000008D2, 0x0000 }, /* R2258 - DRC2LMIX Input 2 Source */ | ||
786 | { 0x000008D3, 0x0080 }, /* R2259 - DRC2LMIX Input 2 Volume */ | ||
787 | { 0x000008D4, 0x0000 }, /* R2260 - DRC2LMIX Input 3 Source */ | ||
788 | { 0x000008D5, 0x0080 }, /* R2261 - DRC2LMIX Input 3 Volume */ | ||
789 | { 0x000008D6, 0x0000 }, /* R2262 - DRC2LMIX Input 4 Source */ | ||
790 | { 0x000008D7, 0x0080 }, /* R2263 - DRC2LMIX Input 4 Volume */ | ||
791 | { 0x000008D8, 0x0000 }, /* R2264 - DRC2RMIX Input 1 Source */ | ||
792 | { 0x000008D9, 0x0080 }, /* R2265 - DRC2RMIX Input 1 Volume */ | ||
793 | { 0x000008DA, 0x0000 }, /* R2266 - DRC2RMIX Input 2 Source */ | ||
794 | { 0x000008DB, 0x0080 }, /* R2267 - DRC2RMIX Input 2 Volume */ | ||
795 | { 0x000008DC, 0x0000 }, /* R2268 - DRC2RMIX Input 3 Source */ | ||
796 | { 0x000008DD, 0x0080 }, /* R2269 - DRC2RMIX Input 3 Volume */ | ||
797 | { 0x000008DE, 0x0000 }, /* R2270 - DRC2RMIX Input 4 Source */ | ||
798 | { 0x000008DF, 0x0080 }, /* R2271 - DRC2RMIX Input 4 Volume */ | ||
799 | { 0x00000900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */ | 779 | { 0x00000900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */ |
800 | { 0x00000901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */ | 780 | { 0x00000901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */ |
801 | { 0x00000902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */ | 781 | { 0x00000902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */ |
@@ -887,7 +867,7 @@ static const struct reg_default wm5102_reg_default[] = { | |||
887 | { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ | 867 | { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ |
888 | { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ | 868 | { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ |
889 | { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ | 869 | { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ |
890 | { 0x00000D41, 0x0000 }, /* R3393 - ADSP2 IRQ0 */ | 870 | { 0x00000D50, 0x0000 }, /* R3408 - AOD wkup and trig */ |
891 | { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ | 871 | { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ |
892 | { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ | 872 | { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ |
893 | { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ | 873 | { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ |
@@ -982,11 +962,6 @@ static const struct reg_default wm5102_reg_default[] = { | |||
982 | { 0x00000E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */ | 962 | { 0x00000E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */ |
983 | { 0x00000E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */ | 963 | { 0x00000E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */ |
984 | { 0x00000E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */ | 964 | { 0x00000E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */ |
985 | { 0x00000E89, 0x0018 }, /* R3721 - DRC2 ctrl1 */ | ||
986 | { 0x00000E8A, 0x0933 }, /* R3722 - DRC2 ctrl2 */ | ||
987 | { 0x00000E8B, 0x0018 }, /* R3723 - DRC2 ctrl3 */ | ||
988 | { 0x00000E8C, 0x0000 }, /* R3724 - DRC2 ctrl4 */ | ||
989 | { 0x00000E8D, 0x0000 }, /* R3725 - DRC2 ctrl5 */ | ||
990 | { 0x00000EC0, 0x0000 }, /* R3776 - HPLPF1_1 */ | 965 | { 0x00000EC0, 0x0000 }, /* R3776 - HPLPF1_1 */ |
991 | { 0x00000EC1, 0x0000 }, /* R3777 - HPLPF1_2 */ | 966 | { 0x00000EC1, 0x0000 }, /* R3777 - HPLPF1_2 */ |
992 | { 0x00000EC4, 0x0000 }, /* R3780 - HPLPF2_1 */ | 967 | { 0x00000EC4, 0x0000 }, /* R3780 - HPLPF2_1 */ |
@@ -997,16 +972,12 @@ static const struct reg_default wm5102_reg_default[] = { | |||
997 | { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ | 972 | { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ |
998 | { 0x00000EE0, 0x0000 }, /* R3808 - ASRC_ENABLE */ | 973 | { 0x00000EE0, 0x0000 }, /* R3808 - ASRC_ENABLE */ |
999 | { 0x00000EE2, 0x0000 }, /* R3810 - ASRC_RATE1 */ | 974 | { 0x00000EE2, 0x0000 }, /* R3810 - ASRC_RATE1 */ |
1000 | { 0x00000EE3, 0x4000 }, /* R3811 - ASRC_RATE2 */ | ||
1001 | { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */ | 975 | { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */ |
1002 | { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */ | 976 | { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */ |
1003 | { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */ | 977 | { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */ |
1004 | { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ | 978 | { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ |
1005 | { 0x00000EF4, 0x0000 }, /* R3828 - ISRC 2 CTRL 2 */ | 979 | { 0x00000EF4, 0x0000 }, /* R3828 - ISRC 2 CTRL 2 */ |
1006 | { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ | 980 | { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ |
1007 | { 0x00000EF6, 0x0000 }, /* R3830 - ISRC 3 CTRL 1 */ | ||
1008 | { 0x00000EF7, 0x0000 }, /* R3831 - ISRC 3 CTRL 2 */ | ||
1009 | { 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */ | ||
1010 | { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ | 981 | { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ |
1011 | { 0x00001101, 0x0000 }, /* R4353 - DSP1 Clocking 1 */ | 982 | { 0x00001101, 0x0000 }, /* R4353 - DSP1 Clocking 1 */ |
1012 | }; | 983 | }; |
@@ -1833,17 +1804,24 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg) | |||
1833 | case ARIZONA_DSP1_STATUS_1: | 1804 | case ARIZONA_DSP1_STATUS_1: |
1834 | case ARIZONA_DSP1_STATUS_2: | 1805 | case ARIZONA_DSP1_STATUS_2: |
1835 | case ARIZONA_DSP1_STATUS_3: | 1806 | case ARIZONA_DSP1_STATUS_3: |
1807 | case ARIZONA_DSP1_SCRATCH_0: | ||
1808 | case ARIZONA_DSP1_SCRATCH_1: | ||
1809 | case ARIZONA_DSP1_SCRATCH_2: | ||
1810 | case ARIZONA_DSP1_SCRATCH_3: | ||
1836 | return true; | 1811 | return true; |
1837 | default: | 1812 | default: |
1838 | return false; | 1813 | if ((reg >= 0x100000 && reg < 0x106000) || |
1814 | (reg >= 0x180000 && reg < 0x180800) || | ||
1815 | (reg >= 0x190000 && reg < 0x194800) || | ||
1816 | (reg >= 0x1a8000 && reg < 0x1a9800)) | ||
1817 | return true; | ||
1818 | else | ||
1819 | return false; | ||
1839 | } | 1820 | } |
1840 | } | 1821 | } |
1841 | 1822 | ||
1842 | static bool wm5102_volatile_register(struct device *dev, unsigned int reg) | 1823 | static bool wm5102_volatile_register(struct device *dev, unsigned int reg) |
1843 | { | 1824 | { |
1844 | if (reg > 0xffff) | ||
1845 | return true; | ||
1846 | |||
1847 | switch (reg) { | 1825 | switch (reg) { |
1848 | case ARIZONA_SOFTWARE_RESET: | 1826 | case ARIZONA_SOFTWARE_RESET: |
1849 | case ARIZONA_DEVICE_REVISION: | 1827 | case ARIZONA_DEVICE_REVISION: |
@@ -1884,12 +1862,22 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) | |||
1884 | case ARIZONA_DSP1_STATUS_1: | 1862 | case ARIZONA_DSP1_STATUS_1: |
1885 | case ARIZONA_DSP1_STATUS_2: | 1863 | case ARIZONA_DSP1_STATUS_2: |
1886 | case ARIZONA_DSP1_STATUS_3: | 1864 | case ARIZONA_DSP1_STATUS_3: |
1865 | case ARIZONA_DSP1_SCRATCH_0: | ||
1866 | case ARIZONA_DSP1_SCRATCH_1: | ||
1867 | case ARIZONA_DSP1_SCRATCH_2: | ||
1868 | case ARIZONA_DSP1_SCRATCH_3: | ||
1887 | case ARIZONA_HEADPHONE_DETECT_2: | 1869 | case ARIZONA_HEADPHONE_DETECT_2: |
1888 | case ARIZONA_HP_DACVAL: | 1870 | case ARIZONA_HP_DACVAL: |
1889 | case ARIZONA_MIC_DETECT_3: | 1871 | case ARIZONA_MIC_DETECT_3: |
1890 | return true; | 1872 | return true; |
1891 | default: | 1873 | default: |
1892 | return false; | 1874 | if ((reg >= 0x100000 && reg < 0x106000) || |
1875 | (reg >= 0x180000 && reg < 0x180800) || | ||
1876 | (reg >= 0x190000 && reg < 0x194800) || | ||
1877 | (reg >= 0x1a8000 && reg < 0x1a9800)) | ||
1878 | return true; | ||
1879 | else | ||
1880 | return false; | ||
1893 | } | 1881 | } |
1894 | } | 1882 | } |
1895 | 1883 | ||
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 57c488d42d3e..803e93fae56a 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -467,7 +467,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
467 | goto err; | 467 | goto err; |
468 | } | 468 | } |
469 | 469 | ||
470 | ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, | 470 | ret = devm_regulator_bulk_get(wm8994->dev, wm8994->num_supplies, |
471 | wm8994->supplies); | 471 | wm8994->supplies); |
472 | if (ret != 0) { | 472 | if (ret != 0) { |
473 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); | 473 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); |
@@ -478,7 +478,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
478 | wm8994->supplies); | 478 | wm8994->supplies); |
479 | if (ret != 0) { | 479 | if (ret != 0) { |
480 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); | 480 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); |
481 | goto err_get; | 481 | goto err; |
482 | } | 482 | } |
483 | 483 | ||
484 | ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET); | 484 | ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET); |
@@ -658,8 +658,6 @@ err_irq: | |||
658 | err_enable: | 658 | err_enable: |
659 | regulator_bulk_disable(wm8994->num_supplies, | 659 | regulator_bulk_disable(wm8994->num_supplies, |
660 | wm8994->supplies); | 660 | wm8994->supplies); |
661 | err_get: | ||
662 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); | ||
663 | err: | 661 | err: |
664 | mfd_remove_devices(wm8994->dev); | 662 | mfd_remove_devices(wm8994->dev); |
665 | return ret; | 663 | return ret; |
@@ -672,7 +670,6 @@ static void wm8994_device_exit(struct wm8994 *wm8994) | |||
672 | wm8994_irq_exit(wm8994); | 670 | wm8994_irq_exit(wm8994); |
673 | regulator_bulk_disable(wm8994->num_supplies, | 671 | regulator_bulk_disable(wm8994->num_supplies, |
674 | wm8994->supplies); | 672 | wm8994->supplies); |
675 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); | ||
676 | } | 673 | } |
677 | 674 | ||
678 | static const struct of_device_id wm8994_of_match[] = { | 675 | static const struct of_device_id wm8994_of_match[] = { |
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index f74b5adca642..468c92303167 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
@@ -678,12 +678,19 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
678 | struct mmc_command *cmd = mrq->cmd; | 678 | struct mmc_command *cmd = mrq->cmd; |
679 | struct mmc_data *data = mrq->data; | 679 | struct mmc_data *data = mrq->data; |
680 | unsigned int data_size = 0; | 680 | unsigned int data_size = 0; |
681 | int err; | ||
681 | 682 | ||
682 | if (host->eject) { | 683 | if (host->eject) { |
683 | cmd->error = -ENOMEDIUM; | 684 | cmd->error = -ENOMEDIUM; |
684 | goto finish; | 685 | goto finish; |
685 | } | 686 | } |
686 | 687 | ||
688 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); | ||
689 | if (err) { | ||
690 | cmd->error = err; | ||
691 | goto finish; | ||
692 | } | ||
693 | |||
687 | mutex_lock(&pcr->pcr_mutex); | 694 | mutex_lock(&pcr->pcr_mutex); |
688 | 695 | ||
689 | rtsx_pci_start_run(pcr); | 696 | rtsx_pci_start_run(pcr); |
@@ -901,6 +908,9 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
901 | if (host->eject) | 908 | if (host->eject) |
902 | return; | 909 | return; |
903 | 910 | ||
911 | if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD)) | ||
912 | return; | ||
913 | |||
904 | mutex_lock(&pcr->pcr_mutex); | 914 | mutex_lock(&pcr->pcr_mutex); |
905 | 915 | ||
906 | rtsx_pci_start_run(pcr); | 916 | rtsx_pci_start_run(pcr); |
@@ -1073,6 +1083,10 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1073 | if (host->eject) | 1083 | if (host->eject) |
1074 | return -ENOMEDIUM; | 1084 | return -ENOMEDIUM; |
1075 | 1085 | ||
1086 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); | ||
1087 | if (err) | ||
1088 | return err; | ||
1089 | |||
1076 | mutex_lock(&pcr->pcr_mutex); | 1090 | mutex_lock(&pcr->pcr_mutex); |
1077 | 1091 | ||
1078 | rtsx_pci_start_run(pcr); | 1092 | rtsx_pci_start_run(pcr); |
@@ -1122,6 +1136,10 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1122 | if (host->eject) | 1136 | if (host->eject) |
1123 | return -ENOMEDIUM; | 1137 | return -ENOMEDIUM; |
1124 | 1138 | ||
1139 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); | ||
1140 | if (err) | ||
1141 | return err; | ||
1142 | |||
1125 | mutex_lock(&pcr->pcr_mutex); | 1143 | mutex_lock(&pcr->pcr_mutex); |
1126 | 1144 | ||
1127 | rtsx_pci_start_run(pcr); | 1145 | rtsx_pci_start_run(pcr); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e6ab071fb6fd..79fbe3832dfc 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -305,6 +305,16 @@ config RTC_DRV_X1205 | |||
305 | This driver can also be built as a module. If so, the module | 305 | This driver can also be built as a module. If so, the module |
306 | will be called rtc-x1205. | 306 | will be called rtc-x1205. |
307 | 307 | ||
308 | config RTC_DRV_PALMAS | ||
309 | tristate "TI Palmas RTC driver" | ||
310 | depends on MFD_PALMAS | ||
311 | help | ||
312 | If you say yes here you get support for the RTC of TI PALMA series PMIC | ||
313 | chips. | ||
314 | |||
315 | This driver can also be built as a module. If so, the module | ||
316 | will be called rtc-palma. | ||
317 | |||
308 | config RTC_DRV_PCF8523 | 318 | config RTC_DRV_PCF8523 |
309 | tristate "NXP PCF8523" | 319 | tristate "NXP PCF8523" |
310 | help | 320 | help |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e8f2e2fee06f..c33f86f1a69b 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -81,6 +81,7 @@ obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o | |||
81 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 81 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
82 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o | 82 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o |
83 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 83 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
84 | obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o | ||
84 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o | 85 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o |
85 | obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o | 86 | obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o |
86 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 87 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c new file mode 100644 index 000000000000..59c42986254e --- /dev/null +++ b/drivers/rtc/rtc-palmas.c | |||
@@ -0,0 +1,339 @@ | |||
1 | /* | ||
2 | * rtc-palmas.c -- Palmas Real Time Clock driver. | ||
3 | |||
4 | * RTC driver for TI Palma series devices like TPS65913, | ||
5 | * TPS65914 power management IC. | ||
6 | * | ||
7 | * Copyright (c) 2012, NVIDIA Corporation. | ||
8 | * | ||
9 | * Author: Laxman Dewangan <ldewangan@nvidia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License as | ||
13 | * published by the Free Software Foundation version 2. | ||
14 | * | ||
15 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
16 | * whether express or implied; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
23 | * 02111-1307, USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/bcd.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/mfd/palmas.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/rtc.h> | ||
34 | #include <linux/types.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/pm.h> | ||
37 | |||
38 | struct palmas_rtc { | ||
39 | struct rtc_device *rtc; | ||
40 | struct device *dev; | ||
41 | unsigned int irq; | ||
42 | }; | ||
43 | |||
44 | /* Total number of RTC registers needed to set time*/ | ||
45 | #define PALMAS_NUM_TIME_REGS (PALMAS_YEARS_REG - PALMAS_SECONDS_REG + 1) | ||
46 | |||
47 | static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
48 | { | ||
49 | unsigned char rtc_data[PALMAS_NUM_TIME_REGS]; | ||
50 | struct palmas *palmas = dev_get_drvdata(dev->parent); | ||
51 | int ret; | ||
52 | |||
53 | /* Copy RTC counting registers to static registers or latches */ | ||
54 | ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, | ||
55 | PALMAS_RTC_CTRL_REG_GET_TIME, PALMAS_RTC_CTRL_REG_GET_TIME); | ||
56 | if (ret < 0) { | ||
57 | dev_err(dev, "RTC CTRL reg update failed, err: %d\n", ret); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | ret = palmas_bulk_read(palmas, PALMAS_RTC_BASE, PALMAS_SECONDS_REG, | ||
62 | rtc_data, PALMAS_NUM_TIME_REGS); | ||
63 | if (ret < 0) { | ||
64 | dev_err(dev, "RTC_SECONDS reg read failed, err = %d\n", ret); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | tm->tm_sec = bcd2bin(rtc_data[0]); | ||
69 | tm->tm_min = bcd2bin(rtc_data[1]); | ||
70 | tm->tm_hour = bcd2bin(rtc_data[2]); | ||
71 | tm->tm_mday = bcd2bin(rtc_data[3]); | ||
72 | tm->tm_mon = bcd2bin(rtc_data[4]) - 1; | ||
73 | tm->tm_year = bcd2bin(rtc_data[5]) + 100; | ||
74 | |||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | static int palmas_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
79 | { | ||
80 | unsigned char rtc_data[PALMAS_NUM_TIME_REGS]; | ||
81 | struct palmas *palmas = dev_get_drvdata(dev->parent); | ||
82 | int ret; | ||
83 | |||
84 | rtc_data[0] = bin2bcd(tm->tm_sec); | ||
85 | rtc_data[1] = bin2bcd(tm->tm_min); | ||
86 | rtc_data[2] = bin2bcd(tm->tm_hour); | ||
87 | rtc_data[3] = bin2bcd(tm->tm_mday); | ||
88 | rtc_data[4] = bin2bcd(tm->tm_mon + 1); | ||
89 | rtc_data[5] = bin2bcd(tm->tm_year - 100); | ||
90 | |||
91 | /* Stop RTC while updating the RTC time registers */ | ||
92 | ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, | ||
93 | PALMAS_RTC_CTRL_REG_STOP_RTC, 0); | ||
94 | if (ret < 0) { | ||
95 | dev_err(dev, "RTC stop failed, err = %d\n", ret); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE, PALMAS_SECONDS_REG, | ||
100 | rtc_data, PALMAS_NUM_TIME_REGS); | ||
101 | if (ret < 0) { | ||
102 | dev_err(dev, "RTC_SECONDS reg write failed, err = %d\n", ret); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | /* Start back RTC */ | ||
107 | ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, | ||
108 | PALMAS_RTC_CTRL_REG_STOP_RTC, PALMAS_RTC_CTRL_REG_STOP_RTC); | ||
109 | if (ret < 0) | ||
110 | dev_err(dev, "RTC start failed, err = %d\n", ret); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | static int palmas_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | ||
115 | { | ||
116 | struct palmas *palmas = dev_get_drvdata(dev->parent); | ||
117 | u8 val; | ||
118 | |||
119 | val = enabled ? PALMAS_RTC_INTERRUPTS_REG_IT_ALARM : 0; | ||
120 | return palmas_write(palmas, PALMAS_RTC_BASE, | ||
121 | PALMAS_RTC_INTERRUPTS_REG, val); | ||
122 | } | ||
123 | |||
124 | static int palmas_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
125 | { | ||
126 | unsigned char alarm_data[PALMAS_NUM_TIME_REGS]; | ||
127 | u32 int_val; | ||
128 | struct palmas *palmas = dev_get_drvdata(dev->parent); | ||
129 | int ret; | ||
130 | |||
131 | ret = palmas_bulk_read(palmas, PALMAS_RTC_BASE, | ||
132 | PALMAS_ALARM_SECONDS_REG, | ||
133 | alarm_data, PALMAS_NUM_TIME_REGS); | ||
134 | if (ret < 0) { | ||
135 | dev_err(dev, "RTC_ALARM_SECONDS read failed, err = %d\n", ret); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | alm->time.tm_sec = bcd2bin(alarm_data[0]); | ||
140 | alm->time.tm_min = bcd2bin(alarm_data[1]); | ||
141 | alm->time.tm_hour = bcd2bin(alarm_data[2]); | ||
142 | alm->time.tm_mday = bcd2bin(alarm_data[3]); | ||
143 | alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1; | ||
144 | alm->time.tm_year = bcd2bin(alarm_data[5]) + 100; | ||
145 | |||
146 | ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_INTERRUPTS_REG, | ||
147 | &int_val); | ||
148 | if (ret < 0) { | ||
149 | dev_err(dev, "RTC_INTERRUPTS reg read failed, err = %d\n", ret); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | if (int_val & PALMAS_RTC_INTERRUPTS_REG_IT_ALARM) | ||
154 | alm->enabled = 1; | ||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static int palmas_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
159 | { | ||
160 | unsigned char alarm_data[PALMAS_NUM_TIME_REGS]; | ||
161 | struct palmas *palmas = dev_get_drvdata(dev->parent); | ||
162 | int ret; | ||
163 | |||
164 | ret = palmas_rtc_alarm_irq_enable(dev, 0); | ||
165 | if (ret < 0) { | ||
166 | dev_err(dev, "Disable RTC alarm failed\n"); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | alarm_data[0] = bin2bcd(alm->time.tm_sec); | ||
171 | alarm_data[1] = bin2bcd(alm->time.tm_min); | ||
172 | alarm_data[2] = bin2bcd(alm->time.tm_hour); | ||
173 | alarm_data[3] = bin2bcd(alm->time.tm_mday); | ||
174 | alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); | ||
175 | alarm_data[5] = bin2bcd(alm->time.tm_year - 100); | ||
176 | |||
177 | ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE, | ||
178 | PALMAS_ALARM_SECONDS_REG, alarm_data, PALMAS_NUM_TIME_REGS); | ||
179 | if (ret < 0) { | ||
180 | dev_err(dev, "ALARM_SECONDS_REG write failed, err = %d\n", ret); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | if (alm->enabled) | ||
185 | ret = palmas_rtc_alarm_irq_enable(dev, 1); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | static int palmas_clear_interrupts(struct device *dev) | ||
190 | { | ||
191 | struct palmas *palmas = dev_get_drvdata(dev->parent); | ||
192 | unsigned int rtc_reg; | ||
193 | int ret; | ||
194 | |||
195 | ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_STATUS_REG, | ||
196 | &rtc_reg); | ||
197 | if (ret < 0) { | ||
198 | dev_err(dev, "RTC_STATUS read failed, err = %d\n", ret); | ||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | ret = palmas_write(palmas, PALMAS_RTC_BASE, PALMAS_RTC_STATUS_REG, | ||
203 | rtc_reg); | ||
204 | if (ret < 0) { | ||
205 | dev_err(dev, "RTC_STATUS write failed, err = %d\n", ret); | ||
206 | return ret; | ||
207 | } | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static irqreturn_t palmas_rtc_interrupt(int irq, void *context) | ||
212 | { | ||
213 | struct palmas_rtc *palmas_rtc = context; | ||
214 | struct device *dev = palmas_rtc->dev; | ||
215 | int ret; | ||
216 | |||
217 | ret = palmas_clear_interrupts(dev); | ||
218 | if (ret < 0) { | ||
219 | dev_err(dev, "RTC interrupt clear failed, err = %d\n", ret); | ||
220 | return IRQ_NONE; | ||
221 | } | ||
222 | |||
223 | rtc_update_irq(palmas_rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
224 | return IRQ_HANDLED; | ||
225 | } | ||
226 | |||
227 | static struct rtc_class_ops palmas_rtc_ops = { | ||
228 | .read_time = palmas_rtc_read_time, | ||
229 | .set_time = palmas_rtc_set_time, | ||
230 | .read_alarm = palmas_rtc_read_alarm, | ||
231 | .set_alarm = palmas_rtc_set_alarm, | ||
232 | .alarm_irq_enable = palmas_rtc_alarm_irq_enable, | ||
233 | }; | ||
234 | |||
235 | static int palmas_rtc_probe(struct platform_device *pdev) | ||
236 | { | ||
237 | struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); | ||
238 | struct palmas_rtc *palmas_rtc = NULL; | ||
239 | int ret; | ||
240 | |||
241 | palmas_rtc = devm_kzalloc(&pdev->dev, sizeof(struct palmas_rtc), | ||
242 | GFP_KERNEL); | ||
243 | if (!palmas_rtc) | ||
244 | return -ENOMEM; | ||
245 | |||
246 | /* Clear pending interrupts */ | ||
247 | ret = palmas_clear_interrupts(&pdev->dev); | ||
248 | if (ret < 0) { | ||
249 | dev_err(&pdev->dev, "clear RTC int failed, err = %d\n", ret); | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | palmas_rtc->dev = &pdev->dev; | ||
254 | platform_set_drvdata(pdev, palmas_rtc); | ||
255 | |||
256 | /* Start RTC */ | ||
257 | ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, | ||
258 | PALMAS_RTC_CTRL_REG_STOP_RTC, | ||
259 | PALMAS_RTC_CTRL_REG_STOP_RTC); | ||
260 | if (ret < 0) { | ||
261 | dev_err(&pdev->dev, "RTC_CTRL write failed, err = %d\n", ret); | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | palmas_rtc->irq = platform_get_irq(pdev, 0); | ||
266 | |||
267 | palmas_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
268 | &palmas_rtc_ops, THIS_MODULE); | ||
269 | if (IS_ERR(palmas_rtc->rtc)) { | ||
270 | ret = PTR_ERR(palmas_rtc->rtc); | ||
271 | dev_err(&pdev->dev, "RTC register failed, err = %d\n", ret); | ||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | ret = request_threaded_irq(palmas_rtc->irq, NULL, | ||
276 | palmas_rtc_interrupt, | ||
277 | IRQF_TRIGGER_LOW | IRQF_ONESHOT | | ||
278 | IRQF_EARLY_RESUME, | ||
279 | dev_name(&pdev->dev), palmas_rtc); | ||
280 | if (ret < 0) { | ||
281 | dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret); | ||
282 | rtc_device_unregister(palmas_rtc->rtc); | ||
283 | return ret; | ||
284 | } | ||
285 | |||
286 | device_set_wakeup_capable(&pdev->dev, 1); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int palmas_rtc_remove(struct platform_device *pdev) | ||
291 | { | ||
292 | struct palmas_rtc *palmas_rtc = platform_get_drvdata(pdev); | ||
293 | |||
294 | palmas_rtc_alarm_irq_enable(&pdev->dev, 0); | ||
295 | free_irq(palmas_rtc->irq, palmas_rtc); | ||
296 | rtc_device_unregister(palmas_rtc->rtc); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | #ifdef CONFIG_PM_SLEEP | ||
301 | static int palmas_rtc_suspend(struct device *dev) | ||
302 | { | ||
303 | struct palmas_rtc *palmas_rtc = dev_get_drvdata(dev); | ||
304 | |||
305 | if (device_may_wakeup(dev)) | ||
306 | enable_irq_wake(palmas_rtc->irq); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int palmas_rtc_resume(struct device *dev) | ||
311 | { | ||
312 | struct palmas_rtc *palmas_rtc = dev_get_drvdata(dev); | ||
313 | |||
314 | if (device_may_wakeup(dev)) | ||
315 | disable_irq_wake(palmas_rtc->irq); | ||
316 | return 0; | ||
317 | } | ||
318 | #endif | ||
319 | |||
320 | static const struct dev_pm_ops palmas_rtc_pm_ops = { | ||
321 | SET_SYSTEM_SLEEP_PM_OPS(palmas_rtc_suspend, palmas_rtc_resume) | ||
322 | }; | ||
323 | |||
324 | static struct platform_driver palmas_rtc_driver = { | ||
325 | .probe = palmas_rtc_probe, | ||
326 | .remove = palmas_rtc_remove, | ||
327 | .driver = { | ||
328 | .owner = THIS_MODULE, | ||
329 | .name = "palmas-rtc", | ||
330 | .pm = &palmas_rtc_pm_ops, | ||
331 | }, | ||
332 | }; | ||
333 | |||
334 | module_platform_driver(palmas_rtc_driver); | ||
335 | |||
336 | MODULE_ALIAS("platform:palmas_rtc"); | ||
337 | MODULE_DESCRIPTION("TI PALMAS series RTC driver"); | ||
338 | MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); | ||
339 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 99899e808c6a..0555ee42d7cb 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -107,7 +107,7 @@ static int omap_ehci_init(struct usb_hcd *hcd) | |||
107 | { | 107 | { |
108 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 108 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
109 | int rc; | 109 | int rc; |
110 | struct ehci_hcd_omap_platform_data *pdata; | 110 | struct usbhs_omap_platform_data *pdata; |
111 | 111 | ||
112 | pdata = hcd->self.controller->platform_data; | 112 | pdata = hcd->self.controller->platform_data; |
113 | 113 | ||
@@ -151,7 +151,7 @@ static int omap_ehci_init(struct usb_hcd *hcd) | |||
151 | } | 151 | } |
152 | 152 | ||
153 | static void disable_put_regulator( | 153 | static void disable_put_regulator( |
154 | struct ehci_hcd_omap_platform_data *pdata) | 154 | struct usbhs_omap_platform_data *pdata) |
155 | { | 155 | { |
156 | int i; | 156 | int i; |
157 | 157 | ||
@@ -176,7 +176,7 @@ static void disable_put_regulator( | |||
176 | static int ehci_hcd_omap_probe(struct platform_device *pdev) | 176 | static int ehci_hcd_omap_probe(struct platform_device *pdev) |
177 | { | 177 | { |
178 | struct device *dev = &pdev->dev; | 178 | struct device *dev = &pdev->dev; |
179 | struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; | 179 | struct usbhs_omap_platform_data *pdata = dev->platform_data; |
180 | struct resource *res; | 180 | struct resource *res; |
181 | struct usb_hcd *hcd; | 181 | struct usb_hcd *hcd; |
182 | void __iomem *regs; | 182 | void __iomem *regs; |
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index 2c9bce050aa9..5ca11b066b7e 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c | |||
@@ -101,6 +101,29 @@ static const struct backlight_ops max8925_backlight_ops = { | |||
101 | .get_brightness = max8925_backlight_get_brightness, | 101 | .get_brightness = max8925_backlight_get_brightness, |
102 | }; | 102 | }; |
103 | 103 | ||
104 | #ifdef CONFIG_OF | ||
105 | static int max8925_backlight_dt_init(struct platform_device *pdev, | ||
106 | struct max8925_backlight_pdata *pdata) | ||
107 | { | ||
108 | struct device_node *nproot = pdev->dev.parent->of_node, *np; | ||
109 | int dual_string; | ||
110 | |||
111 | if (!nproot) | ||
112 | return -ENODEV; | ||
113 | np = of_find_node_by_name(nproot, "backlight"); | ||
114 | if (!np) { | ||
115 | dev_err(&pdev->dev, "failed to find backlight node\n"); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | |||
119 | of_property_read_u32(np, "maxim,max8925-dual-string", &dual_string); | ||
120 | pdata->dual_string = dual_string; | ||
121 | return 0; | ||
122 | } | ||
123 | #else | ||
124 | #define max8925_backlight_dt_init(x, y) (-1) | ||
125 | #endif | ||
126 | |||
104 | static int max8925_backlight_probe(struct platform_device *pdev) | 127 | static int max8925_backlight_probe(struct platform_device *pdev) |
105 | { | 128 | { |
106 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | 129 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); |
@@ -147,6 +170,13 @@ static int max8925_backlight_probe(struct platform_device *pdev) | |||
147 | platform_set_drvdata(pdev, bl); | 170 | platform_set_drvdata(pdev, bl); |
148 | 171 | ||
149 | value = 0; | 172 | value = 0; |
173 | if (pdev->dev.parent->of_node && !pdata) { | ||
174 | pdata = devm_kzalloc(&pdev->dev, | ||
175 | sizeof(struct max8925_backlight_pdata), | ||
176 | GFP_KERNEL); | ||
177 | max8925_backlight_dt_init(pdev, pdata); | ||
178 | } | ||
179 | |||
150 | if (pdata) { | 180 | if (pdata) { |
151 | if (pdata->lxw_scl) | 181 | if (pdata->lxw_scl) |
152 | value |= (1 << 7); | 182 | value |= (1 << 7); |
@@ -158,7 +188,6 @@ static int max8925_backlight_probe(struct platform_device *pdev) | |||
158 | ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 0xfe, value); | 188 | ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 0xfe, value); |
159 | if (ret < 0) | 189 | if (ret < 0) |
160 | goto out_brt; | 190 | goto out_brt; |
161 | |||
162 | backlight_update_status(bl); | 191 | backlight_update_status(bl); |
163 | return 0; | 192 | return 0; |
164 | out_brt: | 193 | out_brt: |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 7f809fd4a57f..26e1fdbddf69 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -364,6 +364,18 @@ config IMX2_WDT | |||
364 | To compile this driver as a module, choose M here: the | 364 | To compile this driver as a module, choose M here: the |
365 | module will be called imx2_wdt. | 365 | module will be called imx2_wdt. |
366 | 366 | ||
367 | config UX500_WATCHDOG | ||
368 | tristate "ST-Ericsson Ux500 watchdog" | ||
369 | depends on MFD_DB8500_PRCMU | ||
370 | select WATCHDOG_CORE | ||
371 | default y | ||
372 | help | ||
373 | Say Y here to include Watchdog timer support for the watchdog | ||
374 | existing in the prcmu of ST-Ericsson Ux500 series platforms. | ||
375 | |||
376 | To compile this driver as a module, choose M here: the | ||
377 | module will be called ux500_wdt. | ||
378 | |||
367 | # AVR32 Architecture | 379 | # AVR32 Architecture |
368 | 380 | ||
369 | config AT32AP700X_WDT | 381 | config AT32AP700X_WDT |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 97bbdb3a4648..bec86ee6e9e3 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -52,6 +52,7 @@ obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o | |||
52 | obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o | 52 | obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o |
53 | obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o | 53 | obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o |
54 | obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o | 54 | obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o |
55 | obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o | ||
55 | 56 | ||
56 | # AVR32 Architecture | 57 | # AVR32 Architecture |
57 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 58 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c new file mode 100644 index 000000000000..a614d84121c3 --- /dev/null +++ b/drivers/watchdog/ux500_wdt.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2011-2013 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * | ||
6 | * Author: Mathieu Poirier <mathieu.poirier@linaro.org> for ST-Ericsson | ||
7 | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/miscdevice.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/watchdog.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/platform_data/ux500_wdt.h> | ||
21 | |||
22 | #include <linux/mfd/dbx500-prcmu.h> | ||
23 | |||
24 | #define WATCHDOG_TIMEOUT 600 /* 10 minutes */ | ||
25 | |||
26 | #define WATCHDOG_MIN 0 | ||
27 | #define WATCHDOG_MAX28 268435 /* 28 bit resolution in ms == 268435.455 s */ | ||
28 | #define WATCHDOG_MAX32 4294967 /* 32 bit resolution in ms == 4294967.295 s */ | ||
29 | |||
30 | static unsigned int timeout = WATCHDOG_TIMEOUT; | ||
31 | module_param(timeout, uint, 0); | ||
32 | MODULE_PARM_DESC(timeout, | ||
33 | "Watchdog timeout in seconds. default=" | ||
34 | __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | ||
35 | |||
36 | static bool nowayout = WATCHDOG_NOWAYOUT; | ||
37 | module_param(nowayout, bool, 0); | ||
38 | MODULE_PARM_DESC(nowayout, | ||
39 | "Watchdog cannot be stopped once started (default=" | ||
40 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
41 | |||
42 | static int ux500_wdt_start(struct watchdog_device *wdd) | ||
43 | { | ||
44 | return prcmu_enable_a9wdog(PRCMU_WDOG_ALL); | ||
45 | } | ||
46 | |||
47 | static int ux500_wdt_stop(struct watchdog_device *wdd) | ||
48 | { | ||
49 | return prcmu_disable_a9wdog(PRCMU_WDOG_ALL); | ||
50 | } | ||
51 | |||
52 | static int ux500_wdt_keepalive(struct watchdog_device *wdd) | ||
53 | { | ||
54 | return prcmu_kick_a9wdog(PRCMU_WDOG_ALL); | ||
55 | } | ||
56 | |||
57 | static int ux500_wdt_set_timeout(struct watchdog_device *wdd, | ||
58 | unsigned int timeout) | ||
59 | { | ||
60 | ux500_wdt_stop(wdd); | ||
61 | prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000); | ||
62 | ux500_wdt_start(wdd); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static const struct watchdog_info ux500_wdt_info = { | ||
68 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | ||
69 | .identity = "Ux500 WDT", | ||
70 | .firmware_version = 1, | ||
71 | }; | ||
72 | |||
73 | static const struct watchdog_ops ux500_wdt_ops = { | ||
74 | .owner = THIS_MODULE, | ||
75 | .start = ux500_wdt_start, | ||
76 | .stop = ux500_wdt_stop, | ||
77 | .ping = ux500_wdt_keepalive, | ||
78 | .set_timeout = ux500_wdt_set_timeout, | ||
79 | }; | ||
80 | |||
81 | static struct watchdog_device ux500_wdt = { | ||
82 | .info = &ux500_wdt_info, | ||
83 | .ops = &ux500_wdt_ops, | ||
84 | .min_timeout = WATCHDOG_MIN, | ||
85 | .max_timeout = WATCHDOG_MAX32, | ||
86 | }; | ||
87 | |||
88 | static int ux500_wdt_probe(struct platform_device *pdev) | ||
89 | { | ||
90 | int ret; | ||
91 | struct ux500_wdt_data *pdata = pdev->dev.platform_data; | ||
92 | |||
93 | if (pdata) { | ||
94 | if (pdata->timeout > 0) | ||
95 | timeout = pdata->timeout; | ||
96 | if (pdata->has_28_bits_resolution) | ||
97 | ux500_wdt.max_timeout = WATCHDOG_MAX28; | ||
98 | } | ||
99 | |||
100 | watchdog_set_nowayout(&ux500_wdt, nowayout); | ||
101 | |||
102 | /* disable auto off on sleep */ | ||
103 | prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false); | ||
104 | |||
105 | /* set HW initial value */ | ||
106 | prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000); | ||
107 | |||
108 | ret = watchdog_register_device(&ux500_wdt); | ||
109 | if (ret) | ||
110 | return ret; | ||
111 | |||
112 | dev_info(&pdev->dev, "initialized\n"); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int ux500_wdt_remove(struct platform_device *dev) | ||
118 | { | ||
119 | watchdog_unregister_device(&ux500_wdt); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | #ifdef CONFIG_PM | ||
125 | static int ux500_wdt_suspend(struct platform_device *pdev, | ||
126 | pm_message_t state) | ||
127 | { | ||
128 | if (watchdog_active(&ux500_wdt)) { | ||
129 | ux500_wdt_stop(&ux500_wdt); | ||
130 | prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true); | ||
131 | |||
132 | prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000); | ||
133 | ux500_wdt_start(&ux500_wdt); | ||
134 | } | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int ux500_wdt_resume(struct platform_device *pdev) | ||
139 | { | ||
140 | if (watchdog_active(&ux500_wdt)) { | ||
141 | ux500_wdt_stop(&ux500_wdt); | ||
142 | prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false); | ||
143 | |||
144 | prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000); | ||
145 | ux500_wdt_start(&ux500_wdt); | ||
146 | } | ||
147 | return 0; | ||
148 | } | ||
149 | #else | ||
150 | #define ux500_wdt_suspend NULL | ||
151 | #define ux500_wdt_resume NULL | ||
152 | #endif | ||
153 | |||
154 | static struct platform_driver ux500_wdt_driver = { | ||
155 | .probe = ux500_wdt_probe, | ||
156 | .remove = ux500_wdt_remove, | ||
157 | .suspend = ux500_wdt_suspend, | ||
158 | .resume = ux500_wdt_resume, | ||
159 | .driver = { | ||
160 | .owner = THIS_MODULE, | ||
161 | .name = "ux500_wdt", | ||
162 | }, | ||
163 | }; | ||
164 | |||
165 | module_platform_driver(ux500_wdt_driver); | ||
166 | |||
167 | MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>"); | ||
168 | MODULE_DESCRIPTION("Ux500 Watchdog Driver"); | ||
169 | MODULE_LICENSE("GPL"); | ||
170 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
171 | MODULE_ALIAS("platform:ux500_wdt"); | ||