aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-pxa/cm-x300.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa/cm-x300.c')
-rw-r--r--arch/arm/mach-pxa/cm-x300.c269
1 files changed, 210 insertions, 59 deletions
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index d37cfa132a6..4d3588d26c2 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -12,6 +12,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/module.h>
#include <linux/kernel.h>
@@ -19,6 +20,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/dm9000.h>
@@ -27,9 +29,13 @@
#include <linux/pwm_backlight.h>
#include <linux/i2c.h>
-#include <linux/i2c/pca953x.h>
+#include <linux/platform_data/pca953x.h>
+#include <linux/i2c/pxa-i2c.h>
#include <linux/mfd/da903x.h>
+#include <linux/regulator/machine.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h>
@@ -38,15 +44,16 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/setup.h>
+#include <asm/system_info.h>
#include <mach/pxa300.h>
#include <mach/pxa27x-udc.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
-#include <plat/i2c.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
#include <mach/audio.h>
+#include <linux/platform_data/usb-pxa3xx-ulpi.h>
#include <asm/mach/map.h>
@@ -58,13 +65,15 @@
#define GPIO82_MMC_IRQ (82)
#define GPIO85_MMC_WP (85)
-#define CM_X300_MMC_IRQ IRQ_GPIO(GPIO82_MMC_IRQ)
+#define CM_X300_MMC_IRQ PXA_GPIO_TO_IRQ(GPIO82_MMC_IRQ)
#define GPIO95_RTC_CS (95)
#define GPIO96_RTC_WR (96)
#define GPIO97_RTC_RD (97)
#define GPIO98_RTC_IO (98)
+#define GPIO_ULPI_PHY_RST (127)
+
static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
/* LCD */
GPIO54_LCD_LDD_0,
@@ -154,10 +163,10 @@ static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
GPIO99_GPIO, /* Ethernet IRQ */
/* RTC GPIOs */
- GPIO95_GPIO, /* RTC CS */
- GPIO96_GPIO, /* RTC WR */
- GPIO97_GPIO, /* RTC RD */
- GPIO98_GPIO, /* RTC IO */
+ GPIO95_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC CS */
+ GPIO96_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC WR */
+ GPIO97_GPIO | MFP_LPM_DRIVE_HIGH, /* RTC RD */
+ GPIO98_GPIO, /* RTC IO */
/* Standard I2C */
GPIO21_I2C_SCL,
@@ -221,8 +230,8 @@ static struct resource dm9000_resources[] = {
.flags = IORESOURCE_MEM,
},
[2] = {
- .start = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO99)),
- .end = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO99)),
+ .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO99)),
+ .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO99)),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
}
};
@@ -289,7 +298,7 @@ static struct pxafb_mach_info cm_x300_lcd = {
static void __init cm_x300_init_lcd(void)
{
- set_pxa_fb_info(&cm_x300_lcd);
+ pxa_set_fb_info(NULL, &cm_x300_lcd);
}
#else
static inline void cm_x300_init_lcd(void) {}
@@ -301,6 +310,7 @@ static struct platform_pwm_backlight_data cm_x300_backlight_data = {
.max_brightness = 100,
.dft_brightness = 100,
.pwm_period_ns = 10000,
+ .enable_gpio = -1,
};
static struct platform_device cm_x300_backlight_device = {
@@ -416,8 +426,9 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
.enable_arbiter = 1,
.keep_config = 1,
- .parts = cm_x300_nand_partitions,
- .nr_parts = ARRAY_SIZE(cm_x300_nand_partitions),
+ .num_cs = 1,
+ .parts[0] = cm_x300_nand_partitions,
+ .nr_parts[0] = ARRAY_SIZE(cm_x300_nand_partitions),
};
static void __init cm_x300_init_nand(void)
@@ -430,7 +441,7 @@ static inline void cm_x300_init_nand(void) {}
#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
static struct pxamci_platform_data cm_x300_mci_platform_data = {
- .detect_delay = 20,
+ .detect_delay_ms = 200,
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
.gpio_card_detect = GPIO82_MMC_IRQ,
.gpio_card_ro = GPIO85_MMC_WP,
@@ -451,7 +462,7 @@ static void cm_x300_mci2_exit(struct device *dev, void *data)
}
static struct pxamci_platform_data cm_x300_mci2_platform_data = {
- .detect_delay = 20,
+ .detect_delay_ms = 200,
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
.init = cm_x300_mci2_init,
.exit = cm_x300_mci2_exit,
@@ -469,6 +480,76 @@ static void __init cm_x300_init_mmc(void)
static inline void cm_x300_init_mmc(void) {}
#endif
+#if defined(CONFIG_PXA310_ULPI)
+static struct clk *pout_clk;
+
+static int cm_x300_ulpi_phy_reset(void)
+{
+ int err;
+
+ /* reset the PHY */
+ err = gpio_request_one(GPIO_ULPI_PHY_RST, GPIOF_OUT_INIT_LOW,
+ "ulpi reset");
+ if (err) {
+ pr_err("failed to request ULPI reset GPIO: %d\n", err);
+ return err;
+ }
+
+ msleep(10);
+ gpio_set_value(GPIO_ULPI_PHY_RST, 1);
+ msleep(10);
+
+ gpio_free(GPIO_ULPI_PHY_RST);
+
+ return 0;
+}
+
+static inline int cm_x300_u2d_init(struct device *dev)
+{
+ int err = 0;
+
+ if (cpu_is_pxa310()) {
+ /* CLK_POUT is connected to the ULPI PHY */
+ pout_clk = clk_get(NULL, "CLK_POUT");
+ if (IS_ERR(pout_clk)) {
+ err = PTR_ERR(pout_clk);
+ pr_err("failed to get CLK_POUT: %d\n", err);
+ return err;
+ }
+ clk_enable(pout_clk);
+
+ err = cm_x300_ulpi_phy_reset();
+ if (err) {
+ clk_disable(pout_clk);
+ clk_put(pout_clk);
+ }
+ }
+
+ return err;
+}
+
+static void cm_x300_u2d_exit(struct device *dev)
+{
+ if (cpu_is_pxa310()) {
+ clk_disable(pout_clk);
+ clk_put(pout_clk);
+ }
+}
+
+static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = {
+ .ulpi_mode = ULPI_SER_6PIN,
+ .init = cm_x300_u2d_init,
+ .exit = cm_x300_u2d_exit,
+};
+
+static void cm_x300_init_u2d(void)
+{
+ pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data);
+}
+#else
+static inline void cm_x300_init_u2d(void) {}
+#endif
+
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int cm_x300_ohci_init(struct device *dev)
{
@@ -584,12 +665,84 @@ static void __init cm_x300_init_rtc(void)
static inline void cm_x300_init_rtc(void) {}
#endif
+/* Battery */
+struct power_supply_info cm_x300_psy_info = {
+ .name = "battery",
+ .technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
+ .voltage_max_design = 4200000,
+ .voltage_min_design = 3000000,
+ .use_for_apm = 1,
+};
+
+static void cm_x300_battery_low(void)
+{
+#if defined(CONFIG_APM_EMULATION)
+ apm_queue_event(APM_LOW_BATTERY);
+#endif
+}
+
+static void cm_x300_battery_critical(void)
+{
+#if defined(CONFIG_APM_EMULATION)
+ apm_queue_event(APM_CRITICAL_SUSPEND);
+#endif
+}
+
+struct da9030_battery_info cm_x300_battery_info = {
+ .battery_info = &cm_x300_psy_info,
+
+ .charge_milliamp = 1000,
+ .charge_millivolt = 4200,
+
+ .vbat_low = 3600,
+ .vbat_crit = 3400,
+ .vbat_charge_start = 4100,
+ .vbat_charge_stop = 4200,
+ .vbat_charge_restart = 4000,
+
+ .vcharge_min = 3200,
+ .vcharge_max = 5500,
+
+ .tbat_low = 197,
+ .tbat_high = 78,
+ .tbat_restart = 100,
+
+ .batmon_interval = 0,
+
+ .battery_low = cm_x300_battery_low,
+ .battery_critical = cm_x300_battery_critical,
+};
+
+static struct regulator_consumer_supply buck2_consumers[] = {
+ REGULATOR_SUPPLY("vcc_core", NULL),
+};
+
+static struct regulator_init_data buck2_data = {
+ .constraints = {
+ .min_uV = 1375000,
+ .max_uV = 1375000,
+ .state_mem = {
+ .enabled = 0,
+ },
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .apply_uV = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck2_consumers),
+ .consumer_supplies = buck2_consumers,
+};
+
/* DA9030 */
struct da903x_subdev_info cm_x300_da9030_subdevs[] = {
{
- .name = "da903x-backlight",
- .id = DA9030_ID_WLED,
- }
+ .name = "da903x-battery",
+ .id = DA9030_ID_BAT,
+ .platform_data = &cm_x300_battery_info,
+ },
+ {
+ .name = "da903x-regulator",
+ .id = DA9030_ID_BUCK2,
+ .platform_data = &buck2_data,
+ },
};
static struct da903x_platform_data cm_x300_da9030_info = {
@@ -599,7 +752,7 @@ static struct da903x_platform_data cm_x300_da9030_info = {
static struct i2c_board_info cm_x300_pmic_info = {
I2C_BOARD_INFO("da9030", 0x49),
- .irq = IRQ_GPIO(0),
+ .irq = IRQ_WAKEUP0,
.platform_data = &cm_x300_da9030_info,
};
@@ -611,41 +764,37 @@ static void __init cm_x300_init_da9030(void)
{
pxa3xx_set_i2c_power_info(&cm_x300_pwr_i2c_info);
i2c_register_board_info(1, &cm_x300_pmic_info, 1);
+ irq_set_irq_wake(IRQ_WAKEUP0, 1);
}
+/* wi2wi gpio setting for system_rev >= 130 */
+static struct gpio cm_x300_wi2wi_gpios[] __initdata = {
+ { 71, GPIOF_OUT_INIT_HIGH, "wlan en" },
+ { 70, GPIOF_OUT_INIT_HIGH, "bt reset" },
+};
+
static void __init cm_x300_init_wi2wi(void)
{
- int bt_reset, wlan_en;
int err;
if (system_rev < 130) {
- wlan_en = 77;
- bt_reset = 78;
- } else {
- wlan_en = 71;
- bt_reset = 70;
+ cm_x300_wi2wi_gpios[0].gpio = 77; /* wlan en */
+ cm_x300_wi2wi_gpios[1].gpio = 78; /* bt reset */
}
/* Libertas and CSR reset */
- err = gpio_request(wlan_en, "wlan en");
+ err = gpio_request_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
if (err) {
- pr_err("CM-X300: failed to request wlan en gpio: %d\n", err);
- } else {
- gpio_direction_output(wlan_en, 1);
- gpio_free(wlan_en);
+ pr_err("failed to request wifi/bt gpios: %d\n", err);
+ return;
}
- err = gpio_request(bt_reset, "bt reset");
- if (err) {
- pr_err("CM-X300: failed to request bt reset gpio: %d\n", err);
- } else {
- gpio_direction_output(bt_reset, 1);
- udelay(10);
- gpio_set_value(bt_reset, 0);
- udelay(10);
- gpio_set_value(bt_reset, 1);
- gpio_free(bt_reset);
- }
+ udelay(10);
+ gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 0);
+ udelay(10);
+ gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 1);
+
+ gpio_free_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
}
/* MFP */
@@ -667,13 +816,15 @@ static void __init cm_x300_init(void)
{
cm_x300_init_mfp();
- pxa_set_ffuart_info(NULL);
pxa_set_btuart_info(NULL);
pxa_set_stuart_info(NULL);
+ if (cpu_is_pxa300())
+ pxa_set_ffuart_info(NULL);
cm_x300_init_da9030();
cm_x300_init_dm9000();
cm_x300_init_lcd();
+ cm_x300_init_u2d();
cm_x300_init_ohci();
cm_x300_init_mmc();
cm_x300_init_nand();
@@ -686,25 +837,25 @@ static void __init cm_x300_init(void)
cm_x300_init_bl();
}
-static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
- char **cmdline, struct meminfo *mi)
+static void __init cm_x300_fixup(struct tag *tags, char **cmdline)
{
- mi->nr_banks = 2;
- mi->bank[0].start = 0xa0000000;
- mi->bank[0].node = 0;
- mi->bank[0].size = (64*1024*1024);
- mi->bank[1].start = 0xc0000000;
- mi->bank[1].node = 0;
- mi->bank[1].size = (64*1024*1024);
+ /* Make sure that mi->bank[0].start = PHYS_ADDR */
+ for (; tags->hdr.size; tags = tag_next(tags))
+ if (tags->hdr.tag == ATAG_MEM &&
+ tags->u.mem.start == 0x80000000) {
+ tags->u.mem.start = 0xa0000000;
+ break;
+ }
}
MACHINE_START(CM_X300, "CM-X300 module")
- .phys_io = 0x40000000,
- .boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
- .map_io = pxa_map_io,
+ .atag_offset = 0x100,
+ .map_io = pxa3xx_map_io,
+ .nr_irqs = PXA_NR_IRQS,
.init_irq = pxa3xx_init_irq,
- .timer = &pxa_timer,
+ .handle_irq = pxa3xx_handle_irq,
+ .init_time = pxa_timer_init,
.init_machine = cm_x300_init,
.fixup = cm_x300_fixup,
+ .restart = pxa_restart,
MACHINE_END