Merge branches 'arm', 'at91', 'bcmring', 'ep93xx', 'mach-types', 'misc' and 'w90x900...
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-ep93xx / core.c
index ce10f5b5dfbb91fe98e7ea7ce726770b11f4bda2..16b92c37ec99a7107ec29ef51103a67ba0c4c191 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/timex.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>
@@ -81,7 +82,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)
 {
@@ -345,8 +346,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) {
@@ -377,7 +378,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;
 
@@ -541,10 +542,8 @@ 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);
@@ -570,6 +569,119 @@ void __init ep93xx_register_i2c(struct i2c_board_info *devices, int 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);
+
+
 extern void ep93xx_gpio_init(void);
 
 void __init ep93xx_init_devices(void)
@@ -585,4 +697,5 @@ void __init ep93xx_init_devices(void)
 
        platform_device_register(&ep93xx_rtc_device);
        platform_device_register(&ep93xx_ohci_device);
+       platform_device_register(&ep93xx_leds);
 }