netns xfrm: fix "ip xfrm state|policy count" misreport
[safe/jmp/linux-2.6] / arch / arm / mach-ep93xx / core.c
index 9399d3a..1f0d665 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
+#include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/bitops.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_core.h>
-#include <linux/device.h>
-#include <linux/mm.h>
 #include <linux/dma-mapping.h>
-#include <linux/time.h>
 #include <linux/timex.h>
-#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
 #include <linux/termios.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
-#include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
 #include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/tlbflush.h>
-#include <asm/pgtable.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_keypad.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
-#include <mach/gpio.h>
 
 #include <asm/hardware/vic.h>
 
@@ -98,7 +84,7 @@ void __init ep93xx_map_io(void)
  */
 static unsigned int last_jiffy_time;
 
-#define TIMER4_TICKS_PER_JIFFY         ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
+#define TIMER4_TICKS_PER_JIFFY         DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ)
 
 static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
 {
@@ -221,7 +207,6 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
        for (i = 0; i < 8; i++) {
                if (status & (1 << i)) {
                        int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
-                       desc = irq_desc + gpio_irq;
                        generic_handle_irq(gpio_irq);
                }
        }
@@ -362,8 +347,8 @@ void __init ep93xx_init_irq(void)
 {
        int gpio_irq;
 
-       vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
-       vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
+       vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
+       vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
 
        for (gpio_irq = gpio_to_irq(0);
             gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
@@ -394,7 +379,7 @@ void __init ep93xx_init_irq(void)
  */
 static DEFINE_SPINLOCK(syscon_swlock);
 
-void ep93xx_syscon_swlocked_write(unsigned int val, unsigned int reg)
+void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg)
 {
        unsigned long flags;
 
@@ -558,22 +543,18 @@ static struct platform_device ep93xx_eth_device = {
 
 void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
 {
-       if (copy_addr) {
-               memcpy(data->dev_addr,
-                       (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
-       }
+       if (copy_addr)
+               memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6);
 
        ep93xx_eth_data = *data;
        platform_device_register(&ep93xx_eth_device);
 }
 
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
-       .sda_pin                = EP93XX_GPIO_LINE_EEDAT,
-       .sda_is_open_drain      = 0,
-       .scl_pin                = EP93XX_GPIO_LINE_EECLK,
-       .scl_is_open_drain      = 0,
-       .udelay                 = 2,
-};
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
 
 static struct platform_device ep93xx_i2c_device = {
        .name                   = "i2c-gpio",
@@ -581,12 +562,249 @@ static struct platform_device ep93xx_i2c_device = {
        .dev.platform_data      = &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+                               struct i2c_board_info *devices, int num)
 {
+       /*
+        * Set the EEPROM interface pin drive type control.
+        * Defines the driver type for the EECLK and EEDAT pins as either
+        * open drain, which will require an external pull-up, or a normal
+        * CMOS driver.
+        */
+       if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+               pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n");
+       if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+               pr_warning("ep93xx: scl != EECLK, open drain has no effect\n");
+
+       __raw_writel((data->sda_is_open_drain << 1) |
+                    (data->scl_is_open_drain << 0),
+                    EP93XX_GPIO_EEDRIVE);
+
+       ep93xx_i2c_data = *data;
        i2c_register_board_info(0, devices, num);
        platform_device_register(&ep93xx_i2c_device);
 }
 
+
+/*************************************************************************
+ * EP93xx LEDs
+ *************************************************************************/
+static struct gpio_led ep93xx_led_pins[] = {
+       {
+               .name                   = "platform:grled",
+               .gpio                   = EP93XX_GPIO_LINE_GRLED,
+       }, {
+               .name                   = "platform:rdled",
+               .gpio                   = EP93XX_GPIO_LINE_RDLED,
+       },
+};
+
+static struct gpio_led_platform_data ep93xx_led_data = {
+       .num_leds       = ARRAY_SIZE(ep93xx_led_pins),
+       .leds           = ep93xx_led_pins,
+};
+
+static struct platform_device ep93xx_leds = {
+       .name           = "leds-gpio",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &ep93xx_led_data,
+       },
+};
+
+
+/*************************************************************************
+ * EP93xx pwm peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_pwm0_resource[] = {
+       {
+               .start  = EP93XX_PWM_PHYS_BASE,
+               .end    = EP93XX_PWM_PHYS_BASE + 0x10 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device ep93xx_pwm0_device = {
+       .name           = "ep93xx-pwm",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(ep93xx_pwm0_resource),
+       .resource       = ep93xx_pwm0_resource,
+};
+
+static struct resource ep93xx_pwm1_resource[] = {
+       {
+               .start  = EP93XX_PWM_PHYS_BASE + 0x20,
+               .end    = EP93XX_PWM_PHYS_BASE + 0x30 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device ep93xx_pwm1_device = {
+       .name           = "ep93xx-pwm",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(ep93xx_pwm1_resource),
+       .resource       = ep93xx_pwm1_resource,
+};
+
+void __init ep93xx_register_pwm(int pwm0, int pwm1)
+{
+       if (pwm0)
+               platform_device_register(&ep93xx_pwm0_device);
+
+       /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */
+       if (pwm1)
+               platform_device_register(&ep93xx_pwm1_device);
+}
+
+int ep93xx_pwm_acquire_gpio(struct platform_device *pdev)
+{
+       int err;
+
+       if (pdev->id == 0) {
+               err = 0;
+       } else if (pdev->id == 1) {
+               err = gpio_request(EP93XX_GPIO_LINE_EGPIO14,
+                                  dev_name(&pdev->dev));
+               if (err)
+                       return err;
+               err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0);
+               if (err)
+                       goto fail;
+
+               /* PWM 1 output on EGPIO[14] */
+               ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG);
+       } else {
+               err = -ENODEV;
+       }
+
+       return err;
+
+fail:
+       gpio_free(EP93XX_GPIO_LINE_EGPIO14);
+       return err;
+}
+EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio);
+
+void ep93xx_pwm_release_gpio(struct platform_device *pdev)
+{
+       if (pdev->id == 1) {
+               gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14);
+               gpio_free(EP93XX_GPIO_LINE_EGPIO14);
+
+               /* EGPIO[14] used for GPIO */
+               ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG);
+       }
+}
+EXPORT_SYMBOL(ep93xx_pwm_release_gpio);
+
+
+/*************************************************************************
+ * EP93xx video peripheral handling
+ *************************************************************************/
+static struct ep93xxfb_mach_info ep93xxfb_data;
+
+static struct resource ep93xx_fb_resource[] = {
+       {
+               .start          = EP93XX_RASTER_PHYS_BASE,
+               .end            = EP93XX_RASTER_PHYS_BASE + 0x800 - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device ep93xx_fb_device = {
+       .name                   = "ep93xx-fb",
+       .id                     = -1,
+       .dev                    = {
+               .platform_data  = &ep93xxfb_data,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .dma_mask               = &ep93xx_fb_device.dev.coherent_dma_mask,
+       },
+       .num_resources          = ARRAY_SIZE(ep93xx_fb_resource),
+       .resource               = ep93xx_fb_resource,
+};
+
+void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data)
+{
+       ep93xxfb_data = *data;
+       platform_device_register(&ep93xx_fb_device);
+}
+
+
+/*************************************************************************
+ * EP93xx matrix keypad peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_keypad_resource[] = {
+       {
+               .start  = EP93XX_KEY_MATRIX_PHYS_BASE,
+               .end    = EP93XX_KEY_MATRIX_PHYS_BASE + 0x0c - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_EP93XX_KEY,
+               .end    = IRQ_EP93XX_KEY,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ep93xx_keypad_device = {
+       .name                   = "ep93xx-keypad",
+       .id                     = -1,
+       .num_resources          = ARRAY_SIZE(ep93xx_keypad_resource),
+       .resource               = ep93xx_keypad_resource,
+};
+
+void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data)
+{
+       ep93xx_keypad_device.dev.platform_data = data;
+       platform_device_register(&ep93xx_keypad_device);
+}
+
+int ep93xx_keypad_acquire_gpio(struct platform_device *pdev)
+{
+       int err;
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               err = gpio_request(EP93XX_GPIO_LINE_C(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_c;
+               err = gpio_request(EP93XX_GPIO_LINE_D(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_d;
+       }
+
+       /* Enable the keypad controller; GPIO ports C and D used for keypad */
+       ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+                                EP93XX_SYSCON_DEVCFG_GONK);
+
+       return 0;
+
+fail_gpio_d:
+       gpio_free(EP93XX_GPIO_LINE_C(i));
+fail_gpio_c:
+       for ( ; i >= 0; --i) {
+               gpio_free(EP93XX_GPIO_LINE_C(i));
+               gpio_free(EP93XX_GPIO_LINE_D(i));
+       }
+       return err;
+}
+EXPORT_SYMBOL(ep93xx_keypad_acquire_gpio);
+
+void ep93xx_keypad_release_gpio(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               gpio_free(EP93XX_GPIO_LINE_C(i));
+               gpio_free(EP93XX_GPIO_LINE_D(i));
+       }
+
+       /* Disable the keypad controller; GPIO ports C and D used for GPIO */
+       ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+                              EP93XX_SYSCON_DEVCFG_GONK);
+}
+EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
+
+
 extern void ep93xx_gpio_init(void);
 
 void __init ep93xx_init_devices(void)
@@ -602,4 +820,5 @@ void __init ep93xx_init_devices(void)
 
        platform_device_register(&ep93xx_rtc_device);
        platform_device_register(&ep93xx_ohci_device);
+       platform_device_register(&ep93xx_leds);
 }