diff options
Diffstat (limited to 'arch/arm/mach-pxa/em-x270.c')
-rw-r--r-- | arch/arm/mach-pxa/em-x270.c | 236 |
1 files changed, 208 insertions, 28 deletions
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index bc0f73fbd4c..63b10d9bb1d 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -28,6 +28,9 @@ #include <linux/spi/libertas_spi.h> #include <linux/power_supply.h> #include <linux/apm-emulation.h> +#include <linux/i2c.h> +#include <linux/i2c/pca953x.h> +#include <linux/regulator/userspace-consumer.h> #include <media/soc_camera.h> @@ -41,7 +44,7 @@ #include <mach/ohci.h> #include <mach/mmc.h> #include <mach/pxa27x_keypad.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/camera.h> #include <mach/pxa2xx_spi.h> @@ -52,23 +55,31 @@ #define GPIO13_MMC_CD (13) #define GPIO95_MMC_WP (95) #define GPIO56_NAND_RB (56) +#define GPIO93_CAM_RESET (93) +#define GPIO16_USB_HUB_RESET (16) /* eXeda specific GPIOs */ #define GPIO114_MMC_CD (114) #define GPIO20_NAND_RB (20) #define GPIO38_SD_PWEN (38) +#define GPIO37_WLAN_RST (37) +#define GPIO95_TOUCHPAD_INT (95) +#define GPIO130_CAM_RESET (130) +#define GPIO10_USB_HUB_RESET (10) /* common GPIOs */ #define GPIO11_NAND_CS (11) -#define GPIO93_CAM_RESET (93) #define GPIO41_ETHIRQ (41) #define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) #define GPIO115_WLAN_PWEN (115) #define GPIO19_WLAN_STRAP (19) +#define GPIO9_USB_VBUS_EN (9) static int mmc_cd; static int nand_rb; static int dm9000_flags; +static int cam_reset; +static int usb_hub_reset; static unsigned long common_pin_config[] = { /* AC'97 */ @@ -180,7 +191,6 @@ static unsigned long common_pin_config[] = { /* power controls */ GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */ - GPIO93_GPIO | MFP_LPM_DRIVE_LOW, /* Camera reset */ GPIO115_GPIO | MFP_LPM_DRIVE_LOW, /* WLAN_PWEN */ /* NAND controls */ @@ -191,14 +201,18 @@ static unsigned long common_pin_config[] = { }; static unsigned long em_x270_pin_config[] = { - GPIO13_GPIO, /* MMC card detect */ - GPIO56_GPIO, /* NAND Ready/Busy */ - GPIO95_GPIO, /* MMC Write protect */ + GPIO13_GPIO, /* MMC card detect */ + GPIO16_GPIO, /* USB hub reset */ + GPIO56_GPIO, /* NAND Ready/Busy */ + GPIO93_GPIO | MFP_LPM_DRIVE_LOW, /* Camera reset */ + GPIO95_GPIO, /* MMC Write protect */ }; static unsigned long exeda_pin_config[] = { + GPIO10_GPIO, /* USB hub reset */ GPIO20_GPIO, /* NAND Ready/Busy */ GPIO38_GPIO | MFP_LPM_DRIVE_LOW, /* SD slot power */ + GPIO95_GPIO, /* touchpad IRQ */ GPIO114_GPIO, /* MMC card detect */ }; @@ -464,18 +478,79 @@ static inline void em_x270_init_nor(void) {} /* PXA27x OHCI controller setup */ #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static struct regulator *em_x270_usb_ldo; + +static int em_x270_usb_hub_init(void) +{ + int err; + + em_x270_usb_ldo = regulator_get(NULL, "vcc usb"); + if (IS_ERR(em_x270_usb_ldo)) + return PTR_ERR(em_x270_usb_ldo); + + err = gpio_request(GPIO9_USB_VBUS_EN, "vbus en"); + if (err) + goto err_free_usb_ldo; + + err = gpio_request(usb_hub_reset, "hub rst"); + if (err) + goto err_free_vbus_gpio; + + /* USB Hub power-on and reset */ + gpio_direction_output(usb_hub_reset, 0); + regulator_enable(em_x270_usb_ldo); + gpio_set_value(usb_hub_reset, 1); + gpio_set_value(usb_hub_reset, 0); + regulator_disable(em_x270_usb_ldo); + regulator_enable(em_x270_usb_ldo); + gpio_set_value(usb_hub_reset, 1); + + /* enable VBUS */ + gpio_direction_output(GPIO9_USB_VBUS_EN, 1); + + return 0; + +err_free_vbus_gpio: + gpio_free(GPIO9_USB_VBUS_EN); +err_free_usb_ldo: + regulator_put(em_x270_usb_ldo); + + return err; +} + static int em_x270_ohci_init(struct device *dev) { + int err; + + /* we don't want to entirely disable USB if the HUB init failed */ + err = em_x270_usb_hub_init(); + if (err) + pr_err("USB Hub initialization failed: %d\n", err); + /* enable port 2 transiever */ UP2OCR = UP2OCR_HXS | UP2OCR_HXOE; return 0; } +static void em_x270_ohci_exit(struct device *dev) +{ + gpio_free(usb_hub_reset); + gpio_free(GPIO9_USB_VBUS_EN); + + if (!IS_ERR(em_x270_usb_ldo)) { + if (regulator_is_enabled(em_x270_usb_ldo)) + regulator_disable(em_x270_usb_ldo); + + regulator_put(em_x270_usb_ldo); + } +} + static struct pxaohci_platform_data em_x270_ohci_platform_data = { .port_mode = PMM_PERPORT_MODE, .flags = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW, .init = em_x270_ohci_init, + .exit = em_x270_ohci_exit, }; static void __init em_x270_init_ohci(void) @@ -661,6 +736,7 @@ static struct pxa2xx_spi_chip em_x270_libertas_chip = { .rx_threshold = 1, .tx_threshold = 1, .timeout = 1000, + .gpio_cs = 14, }; static unsigned long em_x270_libertas_pin_config[] = { @@ -677,33 +753,58 @@ static int em_x270_libertas_setup(struct spi_device *spi) if (err) return err; + err = gpio_request(GPIO19_WLAN_STRAP, "WLAN STRAP"); + if (err) + goto err_free_pwen; + + if (machine_is_exeda()) { + err = gpio_request(GPIO37_WLAN_RST, "WLAN RST"); + if (err) + goto err_free_strap; + + gpio_direction_output(GPIO37_WLAN_RST, 1); + msleep(100); + } + gpio_direction_output(GPIO19_WLAN_STRAP, 1); - mdelay(100); + msleep(100); pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_libertas_pin_config)); gpio_direction_output(GPIO115_WLAN_PWEN, 0); - mdelay(100); + msleep(100); gpio_set_value(GPIO115_WLAN_PWEN, 1); - mdelay(100); + msleep(100); spi->bits_per_word = 16; spi_setup(spi); return 0; + +err_free_strap: + gpio_free(GPIO19_WLAN_STRAP); +err_free_pwen: + gpio_free(GPIO115_WLAN_PWEN); + + return err; } static int em_x270_libertas_teardown(struct spi_device *spi) { gpio_set_value(GPIO115_WLAN_PWEN, 0); gpio_free(GPIO115_WLAN_PWEN); + gpio_free(GPIO19_WLAN_STRAP); + + if (machine_is_exeda()) { + gpio_set_value(GPIO37_WLAN_RST, 0); + gpio_free(GPIO37_WLAN_RST); + } return 0; } struct libertas_spi_platform_data em_x270_libertas_pdata = { .use_dummy_writes = 1, - .gpio_cs = 14, .setup = em_x270_libertas_setup, .teardown = em_x270_libertas_teardown, }; @@ -738,10 +839,14 @@ static void __init em_x270_init_spi(void) static inline void em_x270_init_spi(void) {} #endif -#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE) +#if defined(CONFIG_SND_PXA2XX_LIB_AC97) +static pxa2xx_audio_ops_t em_x270_ac97_info = { + .reset_gpio = 113, +}; + static void __init em_x270_init_ac97(void) { - pxa_set_ac97_info(NULL); + pxa_set_ac97_info(&em_x270_ac97_info); } #else static inline void em_x270_init_ac97(void) {} @@ -863,26 +968,26 @@ static int em_x270_sensor_init(struct device *dev) { int ret; - ret = gpio_request(GPIO93_CAM_RESET, "camera reset"); + ret = gpio_request(cam_reset, "camera reset"); if (ret) return ret; - gpio_direction_output(GPIO93_CAM_RESET, 0); + gpio_direction_output(cam_reset, 0); em_x270_camera_ldo = regulator_get(NULL, "vcc cam"); if (em_x270_camera_ldo == NULL) { - gpio_free(GPIO93_CAM_RESET); + gpio_free(cam_reset); return -ENODEV; } ret = regulator_enable(em_x270_camera_ldo); if (ret) { regulator_put(em_x270_camera_ldo); - gpio_free(GPIO93_CAM_RESET); + gpio_free(cam_reset); return ret; } - gpio_set_value(GPIO93_CAM_RESET, 1); + gpio_set_value(cam_reset, 1); return 0; } @@ -902,7 +1007,7 @@ static int em_x270_sensor_power(struct device *dev, int on) if (on == is_on) return 0; - gpio_set_value(GPIO93_CAM_RESET, !on); + gpio_set_value(cam_reset, !on); if (on) ret = regulator_enable(em_x270_camera_ldo); @@ -912,7 +1017,7 @@ static int em_x270_sensor_power(struct device *dev, int on) if (ret) return ret; - gpio_set_value(GPIO93_CAM_RESET, on); + gpio_set_value(cam_reset, on); return 0; } @@ -929,13 +1034,8 @@ static struct i2c_board_info em_x270_i2c_cam_info[] = { }, }; -static struct i2c_pxa_platform_data em_x270_i2c_info = { - .fast_mode = 1, -}; - static void __init em_x270_init_camera(void) { - pxa_set_i2c_info(&em_x270_i2c_info); i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info)); pxa_set_camera_info(&em_x270_camera_platform_data); } @@ -943,6 +1043,52 @@ static void __init em_x270_init_camera(void) static inline void em_x270_init_camera(void) {} #endif +static struct regulator_bulk_data em_x270_gps_consumer_supply = { + .supply = "vcc gps", +}; + +static struct regulator_userspace_consumer_data em_x270_gps_consumer_data = { + .name = "vcc gps", + .num_supplies = 1, + .supplies = &em_x270_gps_consumer_supply, +}; + +static struct platform_device em_x270_gps_userspace_consumer = { + .name = "reg-userspace-consumer", + .id = 0, + .dev = { + .platform_data = &em_x270_gps_consumer_data, + }, +}; + +static struct regulator_bulk_data em_x270_gprs_consumer_supply = { + .supply = "vcc gprs", +}; + +static struct regulator_userspace_consumer_data em_x270_gprs_consumer_data = { + .name = "vcc gprs", + .num_supplies = 1, + .supplies = &em_x270_gprs_consumer_supply +}; + +static struct platform_device em_x270_gprs_userspace_consumer = { + .name = "reg-userspace-consumer", + .id = 1, + .dev = { + .platform_data = &em_x270_gprs_consumer_data, + } +}; + +static struct platform_device *em_x270_userspace_consumers[] = { + &em_x270_gps_userspace_consumer, + &em_x270_gprs_userspace_consumer, +}; + +static void __init em_x270_userspace_consumers_init(void) +{ + platform_add_devices(ARRAY_AND_SIZE(em_x270_userspace_consumers)); +} + /* DA9030 related initializations */ #define REGULATOR_CONSUMER(_name, _dev, _supply) \ static struct regulator_consumer_supply _name##_consumers[] = { \ @@ -952,11 +1098,11 @@ static inline void em_x270_init_camera(void) {} }, \ } -REGULATOR_CONSUMER(ldo3, NULL, "vcc gps"); +REGULATOR_CONSUMER(ldo3, &em_x270_gps_userspace_consumer.dev, "vcc gps"); REGULATOR_CONSUMER(ldo5, NULL, "vcc cam"); REGULATOR_CONSUMER(ldo10, &pxa_device_mci.dev, "vcc sdio"); REGULATOR_CONSUMER(ldo12, NULL, "vcc usb"); -REGULATOR_CONSUMER(ldo19, NULL, "vcc gprs"); +REGULATOR_CONSUMER(ldo19, &em_x270_gprs_userspace_consumer.dev, "vcc gprs"); #define REGULATOR_INIT(_ldo, _min_uV, _max_uV, _ops_mask) \ static struct regulator_init_data _ldo##_data = { \ @@ -967,6 +1113,7 @@ REGULATOR_CONSUMER(ldo19, NULL, "vcc gprs"); .enabled = 0, \ }, \ .valid_ops_mask = _ops_mask, \ + .apply_uV = 1, \ }, \ .num_consumer_supplies = ARRAY_SIZE(_ldo##_consumers), \ .consumer_supplies = _ldo##_consumers, \ @@ -985,7 +1132,7 @@ struct led_info em_x270_led_info = { }; struct power_supply_info em_x270_psy_info = { - .name = "LP555597P6H-FPS", + .name = "battery", .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, .voltage_max_design = 4200000, .voltage_min_design = 3000000, @@ -1069,6 +1216,29 @@ static void __init em_x270_init_da9030(void) i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1); } +static struct pca953x_platform_data exeda_gpio_ext_pdata = { + .gpio_base = 128, +}; + +static struct i2c_board_info exeda_i2c_info[] = { + { + I2C_BOARD_INFO("pca9555", 0x21), + .platform_data = &exeda_gpio_ext_pdata, + }, +}; + +static struct i2c_pxa_platform_data em_x270_i2c_info = { + .fast_mode = 1, +}; + +static void __init em_x270_init_i2c(void) +{ + pxa_set_i2c_info(&em_x270_i2c_info); + + if (machine_is_exeda()) + i2c_register_board_info(0, ARRAY_AND_SIZE(exeda_i2c_info)); +} + static void __init em_x270_module_init(void) { pr_info("%s\n", __func__); @@ -1077,6 +1247,8 @@ static void __init em_x270_module_init(void) mmc_cd = GPIO13_MMC_CD; nand_rb = GPIO56_NAND_RB; dm9000_flags = DM9000_PLATF_32BITONLY; + cam_reset = GPIO93_CAM_RESET; + usb_hub_reset = GPIO16_USB_HUB_RESET; } static void __init em_x270_exeda_init(void) @@ -1087,12 +1259,18 @@ static void __init em_x270_exeda_init(void) mmc_cd = GPIO114_MMC_CD; nand_rb = GPIO20_NAND_RB; dm9000_flags = DM9000_PLATF_16BITONLY; + cam_reset = GPIO130_CAM_RESET; + usb_hub_reset = GPIO10_USB_HUB_RESET; } static void __init em_x270_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config)); +#ifdef CONFIG_PM + pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP); +#endif + if (machine_is_em_x270()) em_x270_module_init(); else if (machine_is_exeda()) @@ -1111,8 +1289,10 @@ static void __init em_x270_init(void) em_x270_init_keypad(); em_x270_init_gpio_keys(); em_x270_init_ac97(); - em_x270_init_camera(); em_x270_init_spi(); + em_x270_init_i2c(); + em_x270_init_camera(); + em_x270_userspace_consumers_init(); } MACHINE_START(EM_X270, "Compulab EM-X270") |