aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap1/board-ams-delta.c
diff options
context:
space:
mode:
authorJanusz Krzysztofik <jkrzyszt@tis.icnet.pl>2012-03-05 11:05:10 -0500
committerTony Lindgren <tony@atomide.com>2012-03-05 14:17:10 -0500
commitac2885df30e2597d627ad619c01b6fc55ac540a7 (patch)
treed2762c429dd7016f4fb735abad74208b407c15ea /arch/arm/mach-omap1/board-ams-delta.c
parentda564a05b3aefe403062411b67d64b7e992718f7 (diff)
ARM: OMAP1: ams-delta: set up regulator over modem reset GPIO pin
The Amstrad Delta on-board latch2 bit named MODEM_NRESET, now available as a GPIO pin AMS_DELTA_GPIO_PIN_NMODEM_RESET, is used to power up/down (bring into/out of a reset state) two distinct on-board devices simultaneously: the modem, and the voice codec. As a consequence, that bit is, or can be, manipulated concurrently by two drivers, or their platform provided hooks. Instead of updating those drivers to use the gpiolib API as a new method of controlling the MODEM_NRESET pin state, like it was done to other drivers accessing latch2 pins, and still being vulnerable to potential concurrency conflicts, or trying to solve that sharing issue with a custom piece of code, set up a fixed regulator device on top of that GPIO pin, with the intention of updating both drivers to manipulate that regulator, not the GPIO pin directly. Before the ASoC driver is updated and the modem platform data expanded with a power management callback for switching its power, the ams_delta_latch_write() function, which still provides the old API for accessing latch2 functionality from not updated drivers, is modified to toggle the regulator instead of the MODEM_NRESET GPIO pin. A helper function provided for balancing the regulator enable/disable operations, together with the consumer data needed for tracking the regulator state, will be removed once the drivers are updated. Depends on patch series "ARM: OMAP1: ams-delta: replace custom I/O with GPIO". Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap1/board-ams-delta.c')
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c104
1 files changed, 98 insertions, 6 deletions
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index ce50fe137269..949997c35707 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -18,7 +18,11 @@
18#include <linux/input.h> 18#include <linux/input.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/leds.h> 20#include <linux/leds.h>
21#include <linux/mutex.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/regulator/consumer.h>
24#include <linux/regulator/fixed.h>
25#include <linux/regulator/machine.h>
22#include <linux/serial_8250.h> 26#include <linux/serial_8250.h>
23#include <linux/export.h> 27#include <linux/export.h>
24 28
@@ -237,11 +241,6 @@ static const struct gpio latch_gpios[] __initconst = {
237 .label = "scard_cmdvcc", 241 .label = "scard_cmdvcc",
238 }, 242 },
239 { 243 {
240 .gpio = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
241 .flags = GPIOF_OUT_INIT_LOW,
242 .label = "modem_nreset",
243 },
244 {
245 .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC, 244 .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC,
246 .flags = GPIOF_OUT_INIT_LOW, 245 .flags = GPIOF_OUT_INIT_LOW,
247 .label = "modem_codec", 246 .label = "modem_codec",
@@ -258,6 +257,71 @@ static const struct gpio latch_gpios[] __initconst = {
258 }, 257 },
259}; 258};
260 259
260static struct regulator_consumer_supply modem_nreset_consumers[] = {
261 REGULATOR_SUPPLY("RESET#", "serial8250.1"),
262 REGULATOR_SUPPLY("POR", "cx20442-codec"),
263};
264
265static struct regulator_init_data modem_nreset_data = {
266 .constraints = {
267 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
268 .boot_on = 1,
269 },
270 .num_consumer_supplies = ARRAY_SIZE(modem_nreset_consumers),
271 .consumer_supplies = modem_nreset_consumers,
272};
273
274static struct fixed_voltage_config modem_nreset_config = {
275 .supply_name = "modem_nreset",
276 .microvolts = 3300000,
277 .gpio = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
278 .startup_delay = 25000,
279 .enable_high = 1,
280 .enabled_at_boot = 1,
281 .init_data = &modem_nreset_data,
282};
283
284static struct platform_device modem_nreset_device = {
285 .name = "reg-fixed-voltage",
286 .id = -1,
287 .dev = {
288 .platform_data = &modem_nreset_config,
289 },
290};
291
292struct modem_private_data {
293 struct regulator *regulator;
294 struct {
295 struct mutex lock;
296 bool enabled;
297 } consumer;
298};
299
300static int regulator_toggle(struct modem_private_data *priv, bool enable)
301{
302 int err = 0;
303
304 mutex_lock(&priv->consumer.lock);
305 if (IS_ERR(priv->regulator)) {
306 err = PTR_ERR(priv->regulator);
307 } else if (enable) {
308 if (!priv->consumer.enabled) {
309 err = regulator_enable(priv->regulator);
310 priv->consumer.enabled = true;
311 }
312 } else {
313 if (priv->consumer.enabled) {
314 err = regulator_disable(priv->regulator);
315 priv->consumer.enabled = false;
316 }
317 }
318 mutex_unlock(&priv->consumer.lock);
319
320 return err;
321}
322
323static struct modem_private_data modem_priv;
324
261void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value) 325void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value)
262{ 326{
263 int bit = 0; 327 int bit = 0;
@@ -266,7 +330,10 @@ void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value)
266 for (; bit < ngpio; bit++, bitpos = bitpos << 1) { 330 for (; bit < ngpio; bit++, bitpos = bitpos << 1) {
267 if (!(mask & bitpos)) 331 if (!(mask & bitpos))
268 continue; 332 continue;
269 gpio_set_value(base + bit, (value & bitpos) != 0); 333 else if (base + bit == AMS_DELTA_GPIO_PIN_MODEM_NRESET)
334 regulator_toggle(&modem_priv, (value & bitpos) != 0);
335 else
336 gpio_set_value(base + bit, (value & bitpos) != 0);
270 } 337 }
271} 338}
272EXPORT_SYMBOL(ams_delta_latch_write); 339EXPORT_SYMBOL(ams_delta_latch_write);
@@ -496,6 +563,12 @@ static int __init late_init(void)
496 563
497 platform_add_devices(late_devices, ARRAY_SIZE(late_devices)); 564 platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
498 565
566 err = platform_device_register(&modem_nreset_device);
567 if (err) {
568 pr_err("Couldn't register the modem regulator device\n");
569 return err;
570 }
571
499 omap_cfg_reg(M14_1510_GPIO2); 572 omap_cfg_reg(M14_1510_GPIO2);
500 ams_delta_modem_ports[0].irq = 573 ams_delta_modem_ports[0].irq =
501 gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ); 574 gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
@@ -507,6 +580,10 @@ static int __init late_init(void)
507 } 580 }
508 gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ); 581 gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
509 582
583 /* Initialize the modem_nreset regulator consumer before use */
584 mutex_init(&modem_priv.consumer.lock);
585 modem_priv.regulator = ERR_PTR(-ENODEV);
586
510 ams_delta_latch2_write( 587 ams_delta_latch2_write(
511 AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC, 588 AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC,
512 AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC); 589 AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC);
@@ -514,8 +591,23 @@ static int __init late_init(void)
514 err = platform_device_register(&ams_delta_modem_device); 591 err = platform_device_register(&ams_delta_modem_device);
515 if (err) 592 if (err)
516 goto gpio_free; 593 goto gpio_free;
594
595 /*
596 * Once the modem device is registered, the modem_nreset
597 * regulator can be requested on behalf of that device.
598 * The regulator is used via ams_delta_latch_write()
599 * by the modem and ASoC drivers until updated.
600 */
601 modem_priv.regulator = regulator_get(&ams_delta_modem_device.dev,
602 "RESET#");
603 if (IS_ERR(modem_priv.regulator)) {
604 err = PTR_ERR(modem_priv.regulator);
605 goto unregister;
606 }
517 return 0; 607 return 0;
518 608
609unregister:
610 platform_device_unregister(&ams_delta_modem_device);
519gpio_free: 611gpio_free:
520 gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ); 612 gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
521 return err; 613 return err;