daily pastebin goal
3%
SHARE
TWEET

pi gpio-keys and gpio-mouse

a guest Jun 19th, 2012 2,648 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  *  linux/arch/arm/mach-bcm2708/bcm2708.c
  3.  *
  4.  *  Copyright (C) 2010 Broadcom
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include <linux/init.h>
  22. #include <linux/device.h>
  23. #include <linux/dma-mapping.h>
  24. #include <linux/serial_8250.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/sysdev.h>
  27. #include <linux/interrupt.h>
  28. #include <linux/amba/bus.h>
  29. #include <linux/amba/clcd.h>
  30. #include <linux/clockchips.h>
  31. #include <linux/cnt32_to_63.h>
  32. #include <linux/io.h>
  33. #include <linux/module.h>
  34.  
  35. #include <linux/version.h>
  36. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
  37. #include <linux/clkdev.h>
  38. #else
  39. #include <asm/clkdev.h>
  40. #endif
  41. #include <asm/system.h>
  42. #include <mach/hardware.h>
  43. #include <asm/irq.h>
  44. #include <linux/leds.h>
  45. #include <asm/mach-types.h>
  46.  
  47. #include <asm/mach/arch.h>
  48. #include <asm/mach/flash.h>
  49. #include <asm/mach/irq.h>
  50. #include <asm/mach/time.h>
  51. #include <asm/mach/map.h>
  52.  
  53. #include <mach/timex.h>
  54. #include <mach/dma.h>
  55. #include <mach/vcio.h>
  56.  
  57. #include "bcm2708.h"
  58. #include "armctrl.h"
  59. #include "clock.h"
  60.  
  61.  
  62. /* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to
  63.  * give us IO access only to 64Mbytes of physical memory (26 bits).  We could
  64.  * represent this window by setting our dmamasks to 26 bits but, in fact
  65.  * we're not going to use addresses outside this range (they're not in real
  66.  * memory) so we don't bother.
  67.  *
  68.  * In the future we might include code to use this IOMMU to remap other
  69.  * physical addresses onto VideoCore memory then the use of 32-bits would be
  70.  * more legitimate.
  71.  */
  72. #define DMA_MASK_BITS_COMMON 32
  73.  
  74. /* command line parameters */
  75. static unsigned boardrev, serial;
  76. static void __init bcm2708_init_led(void);
  77. // Reggie added, gpio-keys init declaration
  78. static void __init bcm2708_init_gpio_keys(void);
  79. static void __init bcm2708_init_gpio_mouse(void);
  80. void __init bcm2708_init_irq(void)
  81. {
  82.         armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0);
  83. }
  84.  
  85. static struct map_desc bcm2708_io_desc[] __initdata = {
  86.         {
  87.          .virtual = IO_ADDRESS(ARMCTRL_BASE),
  88.          .pfn = __phys_to_pfn(ARMCTRL_BASE),
  89.          .length = SZ_4K,
  90.          .type = MT_DEVICE},
  91.         {
  92.          .virtual = IO_ADDRESS(UART0_BASE),
  93.          .pfn = __phys_to_pfn(UART0_BASE),
  94.          .length = SZ_4K,
  95.          .type = MT_DEVICE},
  96.         {
  97.          .virtual = IO_ADDRESS(UART1_BASE),
  98.          .pfn = __phys_to_pfn(UART1_BASE),
  99.          .length = SZ_4K,
  100.          .type = MT_DEVICE},
  101. #ifdef CONFIG_MMC_BCM2708       /* broadcom legacy SD */
  102.         {
  103.          .virtual = IO_ADDRESS(MMCI0_BASE),
  104.          .pfn = __phys_to_pfn(MMCI0_BASE),
  105.          .length = SZ_4K,
  106.          .type = MT_DEVICE},
  107. #endif
  108.         {
  109.          .virtual = IO_ADDRESS(DMA_BASE),
  110.          .pfn = __phys_to_pfn(DMA_BASE),
  111.          .length = SZ_4K,
  112.          .type = MT_DEVICE},
  113.         {
  114.          .virtual = IO_ADDRESS(MCORE_BASE),
  115.          .pfn = __phys_to_pfn(MCORE_BASE),
  116.          .length = SZ_4K,
  117.          .type = MT_DEVICE},
  118.         {
  119.          .virtual = IO_ADDRESS(ST_BASE),
  120.          .pfn = __phys_to_pfn(ST_BASE),
  121.          .length = SZ_4K,
  122.          .type = MT_DEVICE},
  123.         {
  124.          .virtual = IO_ADDRESS(USB_BASE),
  125.          .pfn = __phys_to_pfn(USB_BASE),
  126.          .length = SZ_128K,
  127.          .type = MT_DEVICE},
  128.         {
  129.          .virtual = IO_ADDRESS(PM_BASE),
  130.          .pfn = __phys_to_pfn(PM_BASE),
  131.          .length = SZ_4K,
  132.          .type = MT_DEVICE},
  133.         {
  134.          .virtual = IO_ADDRESS(GPIO_BASE),
  135.          .pfn = __phys_to_pfn(GPIO_BASE),
  136.          .length = SZ_4K,
  137.          .type = MT_DEVICE}
  138. };
  139.  
  140. void __init bcm2708_map_io(void)
  141. {
  142.         iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc));
  143. }
  144.  
  145. // The STC is a free running counter that increments at the rate of 1MHz
  146. #define STC_FREQ_HZ 1000000
  147.  
  148. static cycle_t stc_read_cycles(struct clocksource *cs)
  149. {
  150.         /* STC: a free running counter that increments at the rate of 1MHz */
  151.         return (cycle_t) readl(__io_address(ST_BASE + 0x04));
  152. }
  153.  
  154. static struct clocksource clocksource_stc = {
  155.         .name = "stc",
  156.         .rating = 300,
  157.         .read = stc_read_cycles,
  158.         .mask = CLOCKSOURCE_MASK(32),
  159.         .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  160. };
  161.  
  162. unsigned long frc_clock_ticks32(void)
  163. {
  164.         return (unsigned long)stc_read_cycles(&clocksource_stc);
  165. }
  166.  
  167. static void __init bcm2708_clocksource_init(void)
  168. {
  169.         // calculate .shift and .mult values and register clocksource
  170.         if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) {
  171.                 printk(KERN_ERR "timer: failed to initialize clock "
  172.                        "source %s\n", clocksource_stc.name);
  173.         }
  174. }
  175.  
  176. unsigned long long sched_clock(void)
  177. {
  178.         return clocksource_cyc2ns(clocksource_stc.read(&clocksource_stc),
  179.                                   clocksource_stc.mult, clocksource_stc.shift);
  180. }
  181.  
  182. /*
  183.  * These are fixed clocks.
  184.  */
  185. static struct clk ref24_clk = {
  186.         .rate = 3000000,        /* The UART is clocked at 3MHz via APB_CLK */
  187. };
  188.  
  189. static struct clk osc_clk = {
  190. #ifdef CONFIG_ARCH_BCM2708_CHIPIT
  191.         .rate = 27000000,
  192. #else
  193.         .rate = 500000000,      /* ARM clock is set from the VideoCore booter */
  194. #endif
  195. };
  196.  
  197. /* warning - the USB needs a clock > 34MHz */
  198.  
  199. #ifdef CONFIG_MMC_BCM2708
  200. static struct clk sdhost_clk = {
  201. #ifdef CONFIG_ARCH_BCM2708_CHIPIT
  202.         .rate = 4000000,        /* 4MHz */
  203. #else
  204.         .rate = 250000000,      /* 250MHz */
  205. #endif
  206. };
  207. #endif
  208.  
  209. static struct clk_lookup lookups[] = {
  210.         {                       /* UART0 */
  211.          .dev_id = "dev:f1",
  212.          .clk = &ref24_clk,
  213.          },
  214.         {                       /* USB */
  215.          .dev_id = "bcm2708_usb",
  216.          .clk = &osc_clk,
  217. #ifdef CONFIG_MMC_BCM2708
  218.          },
  219.         {                       /* MCI */
  220.          .dev_id = "bcm2708_mci.0",
  221.          .clk = &sdhost_clk,
  222. #endif
  223.          }
  224. };
  225.  
  226. #define UART0_IRQ       { IRQ_UART, NO_IRQ }
  227. #define UART0_DMA       { 15, 14 }
  228.  
  229. AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
  230.  
  231. static struct amba_device *amba_devs[] __initdata = {
  232.         &uart0_device,
  233. };
  234.  
  235. static struct resource bcm2708_dmaman_resources[] = {
  236.         {
  237.          .start = DMA_BASE,
  238.          .end = DMA_BASE + SZ_4K - 1,
  239.          .flags = IORESOURCE_MEM,
  240.          }
  241. };
  242.  
  243. static struct platform_device bcm2708_dmaman_device = {
  244.         .name = BCM_DMAMAN_DRIVER_NAME,
  245.         .id = 0,                /* first bcm2708_dma */
  246.         .resource = bcm2708_dmaman_resources,
  247.         .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources),
  248. };
  249.  
  250. #ifdef CONFIG_MMC_BCM2708
  251. static struct resource bcm2708_mci_resources[] = {
  252.         {
  253.          .start = MMCI0_BASE,
  254.          .end = MMCI0_BASE + SZ_4K - 1,
  255.          .flags = IORESOURCE_MEM,
  256.          },
  257.         {
  258.          .start = IRQ_SDIO,
  259.          .end = IRQ_SDIO,
  260.          .flags = IORESOURCE_IRQ,
  261.          }
  262. };
  263.  
  264. static struct platform_device bcm2708_mci_device = {
  265.         .name = "bcm2708_mci",
  266.         .id = 0,                /* first bcm2708_mci */
  267.         .resource = bcm2708_mci_resources,
  268.         .num_resources = ARRAY_SIZE(bcm2708_mci_resources),
  269.         .dev = {
  270.                 .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
  271.                 },
  272. };
  273. #endif /* CONFIG_MMC_BCM2708 */
  274.  
  275. static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
  276.  
  277. static struct platform_device bcm2708_fb_device = {
  278.         .name = "bcm2708_fb",
  279.         .id = -1,               /* only one bcm2708_fb */
  280.         .resource = NULL,
  281.         .num_resources = 0,
  282.         .dev = {
  283.                 .dma_mask = &fb_dmamask,
  284.                 .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
  285.                 },
  286. };
  287.  
  288. static struct plat_serial8250_port bcm2708_uart1_platform_data[] = {
  289.         {
  290.          .mapbase = UART1_BASE + 0x40,
  291.          .irq = IRQ_AUX,
  292.          .uartclk = 125000000,
  293.          .regshift = 2,
  294.          .iotype = UPIO_MEM,
  295.          .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST,
  296.          .type = PORT_8250,
  297.          },
  298.         {},
  299. };
  300.  
  301. static struct platform_device bcm2708_uart1_device = {
  302.         .name = "serial8250",
  303.         .id = PLAT8250_DEV_PLATFORM,
  304.         .dev = {
  305.                 .platform_data = bcm2708_uart1_platform_data,
  306.                 },
  307. };
  308.  
  309. static struct resource bcm2708_usb_resources[] = {
  310.         [0] = {
  311.                .start = USB_BASE,
  312.                .end = USB_BASE + SZ_128K - 1,
  313.                .flags = IORESOURCE_MEM,
  314.                },
  315.         [1] = {
  316.                .start = IRQ_USB,
  317.                .end = IRQ_USB,
  318.                .flags = IORESOURCE_IRQ,
  319.                },
  320. };
  321.  
  322. static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
  323.  
  324. static struct platform_device bcm2708_usb_device = {
  325.         .name = "bcm2708_usb",
  326.         .id = -1,               /* only one bcm2708_usb */
  327.         .resource = bcm2708_usb_resources,
  328.         .num_resources = ARRAY_SIZE(bcm2708_usb_resources),
  329.         .dev = {
  330.                 .dma_mask = &usb_dmamask,
  331.                 .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
  332.                 },
  333. };
  334.  
  335. static struct resource bcm2708_vcio_resources[] = {
  336.         [0] = {                 /* mailbox/semaphore/doorbell access */
  337.                .start = MCORE_BASE,
  338.                .end = MCORE_BASE + SZ_4K - 1,
  339.                .flags = IORESOURCE_MEM,
  340.                },
  341. };
  342.  
  343. static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
  344.  
  345. static struct platform_device bcm2708_vcio_device = {
  346.         .name = BCM_VCIO_DRIVER_NAME,
  347.         .id = -1,               /* only one VideoCore I/O area */
  348.         .resource = bcm2708_vcio_resources,
  349.         .num_resources = ARRAY_SIZE(bcm2708_vcio_resources),
  350.         .dev = {
  351.                 .dma_mask = &vcio_dmamask,
  352.                 .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
  353.                 },
  354. };
  355.  
  356. #ifdef CONFIG_BCM2708_GPIO
  357. #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
  358.  
  359. static struct resource bcm2708_gpio_resources[] = {
  360.         [0] = {                 /* general purpose I/O */
  361.                .start = GPIO_BASE,
  362.                .end = GPIO_BASE + SZ_4K - 1,
  363.                .flags = IORESOURCE_MEM,
  364.                },
  365. };
  366.  
  367. static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
  368.  
  369. static struct platform_device bcm2708_gpio_device = {
  370.         .name = BCM_GPIO_DRIVER_NAME,
  371.         .id = -1,               /* only one VideoCore I/O area */
  372.         .resource = bcm2708_gpio_resources,
  373.         .num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
  374.         .dev = {
  375.                 .dma_mask = &gpio_dmamask,
  376.                 .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
  377.                 },
  378. };
  379. #endif
  380.  
  381. static struct resource bcm2708_systemtimer_resources[] = {
  382.         [0] = {                 /* system timer access */
  383.                .start = ST_BASE,
  384.                .end = ST_BASE + SZ_4K - 1,
  385.                .flags = IORESOURCE_MEM,
  386.                },
  387.         {
  388.          .start = IRQ_TIMER3,
  389.          .end = IRQ_TIMER3,
  390.          .flags = IORESOURCE_IRQ,
  391.          }
  392.  
  393. };
  394.  
  395. static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
  396.  
  397. static struct platform_device bcm2708_systemtimer_device = {
  398.         .name = "bcm2708_systemtimer",
  399.         .id = -1,               /* only one VideoCore I/O area */
  400.         .resource = bcm2708_systemtimer_resources,
  401.         .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources),
  402.         .dev = {
  403.                 .dma_mask = &systemtimer_dmamask,
  404.                 .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
  405.                 },
  406. };
  407.  
  408. #ifdef CONFIG_MMC_SDHCI_BCM2708 /* Arasan emmc SD */
  409. static struct resource bcm2708_emmc_resources[] = {
  410.         [0] = {
  411.                .start = EMMC_BASE,
  412.                .end = EMMC_BASE + SZ_256 - 1,   /* we only need this area */
  413.                /* the memory map actually makes SZ_4K available  */
  414.                .flags = IORESOURCE_MEM,
  415.                },
  416.         [1] = {
  417.                .start = IRQ_ARASANSDIO,
  418.                .end = IRQ_ARASANSDIO,
  419.                .flags = IORESOURCE_IRQ,
  420.                },
  421. };
  422.  
  423. static u64 bcm2708_emmc_dmamask = 0xffffffffUL;
  424.  
  425. struct platform_device bcm2708_emmc_device = {
  426.         .name = "bcm2708_sdhci",
  427.         .id = 0,
  428.         .num_resources = ARRAY_SIZE(bcm2708_emmc_resources),
  429.         .resource = bcm2708_emmc_resources,
  430.         .dev = {
  431.                 .dma_mask = &bcm2708_emmc_dmamask,
  432.                 .coherent_dma_mask = 0xffffffffUL},
  433. };
  434. #endif /* CONFIG_MMC_SDHCI_BCM2708 */
  435.  
  436. static struct resource bcm2708_powerman_resources[] = {
  437.         [0] = {
  438.                .start = PM_BASE,
  439.                .end = PM_BASE + SZ_256 - 1,
  440.                .flags = IORESOURCE_MEM,
  441.                },
  442. };
  443.  
  444. static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
  445.  
  446. struct platform_device bcm2708_powerman_device = {
  447.         .name = "bcm2708_powerman",
  448.         .id = 0,
  449.         .num_resources = ARRAY_SIZE(bcm2708_powerman_resources),
  450.         .resource = bcm2708_powerman_resources,
  451.         .dev = {
  452.                 .dma_mask = &powerman_dmamask,
  453.                 .coherent_dma_mask = 0xffffffffUL},
  454. };
  455.  
  456. static struct platform_device bcm2708_alsa_devices[] = {
  457.         [0] = {
  458.                .name = "bcm2835_AUD0",
  459.                .id = 0,         /* first audio device */
  460.                .resource = 0,
  461.                .num_resources = 0,
  462.                },
  463. };
  464.  
  465. int __init bcm_register_device(struct platform_device *pdev)
  466. {
  467.         int ret;
  468.  
  469.         ret = platform_device_register(pdev);
  470.         if (ret)
  471.                 pr_debug("Unable to register platform device '%s': %d\n",
  472.                          pdev->name, ret);
  473.  
  474.         return ret;
  475. }
  476.  
  477. void __init bcm2708_init(void)
  478. {
  479.         int i;
  480.  
  481.         for (i = 0; i < ARRAY_SIZE(lookups); i++)
  482.                 clkdev_add(&lookups[i]);
  483.  
  484.         bcm_register_device(&bcm2708_dmaman_device);
  485.         bcm_register_device(&bcm2708_vcio_device);
  486. #ifdef CONFIG_BCM2708_GPIO
  487.         bcm_register_device(&bcm2708_gpio_device);
  488. #endif
  489.         bcm_register_device(&bcm2708_systemtimer_device);
  490. #ifdef CONFIG_MMC_BCM2708
  491.         bcm_register_device(&bcm2708_mci_device);
  492. #endif
  493.         bcm_register_device(&bcm2708_fb_device);
  494.         bcm_register_device(&bcm2708_usb_device);
  495.         bcm_register_device(&bcm2708_uart1_device);
  496.         bcm_register_device(&bcm2708_powerman_device);
  497. #ifdef CONFIG_MMC_SDHCI_BCM2708
  498.         bcm_register_device(&bcm2708_emmc_device);
  499. #endif
  500.         bcm2708_init_led();
  501.         // Reggie added, gpio-keys initialisation
  502.         bcm2708_init_gpio_keys();
  503.         bcm2708_init_gpio_mouse();
  504.         for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
  505.                 bcm_register_device(&bcm2708_alsa_devices[i]);
  506.  
  507. #ifdef CONFIG_BCM2708_VCMEM
  508.         {
  509.                 extern void vc_mem_connected_init(void);
  510.                 vc_mem_connected_init();
  511.         }
  512. #endif
  513.         for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
  514.                 struct amba_device *d = amba_devs[i];
  515.                 amba_device_register(d, &iomem_resource);
  516.         }
  517.         system_rev = boardrev;
  518.         system_serial_low = serial;
  519. }
  520.  
  521. #define TIMER_PERIOD 10000      /* HZ in microsecs */
  522.  
  523. static void timer_set_mode(enum clock_event_mode mode,
  524.                            struct clock_event_device *clk)
  525. {
  526.         unsigned long stc;
  527.  
  528.         switch (mode) {
  529.         case CLOCK_EVT_MODE_PERIODIC:
  530.                 stc = readl(__io_address(ST_BASE + 0x04));
  531.                 writel(stc + TIMER_PERIOD, __io_address(ST_BASE + 0x18));       /* stc3 */
  532.                 break;
  533.         case CLOCK_EVT_MODE_ONESHOT:
  534.         case CLOCK_EVT_MODE_UNUSED:
  535.         case CLOCK_EVT_MODE_SHUTDOWN:
  536.         default:
  537.                 printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n",
  538.                        (int)mode);
  539.                 break;
  540.         }
  541.  
  542. }
  543.  
  544. static int timer_set_next_event(unsigned long cycles,
  545.                                 struct clock_event_device *unused)
  546. {
  547.         unsigned long stc;
  548.  
  549.         stc = readl(__io_address(ST_BASE + 0x04));
  550.         writel(stc + cycles, __io_address(ST_BASE + 0x18));     /* stc3 */
  551.         return 0;
  552. }
  553.  
  554. static struct clock_event_device timer0_clockevent = {
  555.         .name = "timer0",
  556.         .shift = 32,
  557.         .features = CLOCK_EVT_FEAT_ONESHOT,
  558.         .set_mode = timer_set_mode,
  559.         .set_next_event = timer_set_next_event,
  560. };
  561.  
  562. /*
  563.  * IRQ handler for the timer
  564.  */
  565. static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id)
  566. {
  567.         struct clock_event_device *evt = &timer0_clockevent;
  568.  
  569.         writel(1 << 3, __io_address(ST_BASE + 0x00));   /* stcs clear timer int */
  570.  
  571.         evt->event_handler(evt);
  572.  
  573.         return IRQ_HANDLED;
  574. }
  575.  
  576. static struct irqaction bcm2708_timer_irq = {
  577.         .name = "BCM2708 Timer Tick",
  578.         .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
  579.         .handler = bcm2708_timer_interrupt,
  580. };
  581.  
  582. /*
  583.  * Set up timer interrupt, and return the current time in seconds.
  584.  */
  585. static void __init bcm2708_timer_init(void)
  586. {
  587.         /* init high res timer */
  588.         bcm2708_clocksource_init();
  589.  
  590.         /*
  591.          * Initialise to a known state (all timers off)
  592.          */
  593.         writel(0, __io_address(ARM_T_CONTROL));
  594.         /*
  595.          * Make irqs happen for the system timer
  596.          */
  597.         setup_irq(IRQ_TIMER3, &bcm2708_timer_irq);
  598.  
  599.         timer0_clockevent.mult =
  600.             div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift);
  601.         timer0_clockevent.max_delta_ns =
  602.             clockevent_delta2ns(0xffffffff, &timer0_clockevent);
  603.         timer0_clockevent.min_delta_ns =
  604.             clockevent_delta2ns(0xf, &timer0_clockevent);
  605.  
  606.         timer0_clockevent.cpumask = cpumask_of(0);
  607.         clockevents_register_device(&timer0_clockevent);
  608. }
  609.  
  610. struct sys_timer bcm2708_timer = {
  611.         .init = bcm2708_timer_init,
  612. };
  613.  
  614. #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
  615. #include <linux/leds.h>
  616.  
  617. static struct gpio_led bcm2708_leds[] = {
  618.         [0] = {
  619.                .gpio = 16,
  620.                .name = "led0",
  621.                .default_trigger = "mmc0",
  622.                .active_low = 1,
  623.                },
  624. };
  625.  
  626. static struct gpio_led_platform_data bcm2708_led_pdata = {
  627.         .num_leds = ARRAY_SIZE(bcm2708_leds),
  628.         .leds = bcm2708_leds,
  629. };
  630.  
  631. static struct platform_device bcm2708_led_device = {
  632.         .name = "leds-gpio",
  633.         .id = -1,
  634.         .dev = {
  635.                 .platform_data = &bcm2708_led_pdata,
  636.                 },
  637. };
  638.  
  639. static void __init bcm2708_init_led(void)
  640. {
  641.         platform_device_register(&bcm2708_led_device);
  642. }
  643. #else
  644. static inline void bcm2708_init_led(void)
  645. {
  646. }
  647. #endif
  648. // Reggie added, simple gpio keys polled driver, adds button support via gpio
  649. // will be useful for embedded devices, see gpio-mouse, gpio-fan and rotary-encoder
  650. // for other examples of gpio access to devices from the linux kernel
  651. // this will use GPIO4,17,21,22 as a simple test, they will be set to active_low
  652. // so should have a pullup added to each pin and button tied to ground.
  653. // We have to use polled at the moment because the current kernel doesn't have
  654. // code to handle an interrupt driven gpio-keys driver, which would've been much nicer
  655. // you should check the wiki to make sure that these gpio are correctly configured
  656. // and see whether they are physically pulled up on the schematic, if they're not
  657. // add a 10k pullup to the gpio-keys pins and tie the button to gnd
  658. // buttons are set active low, so closing the switch should pull them to ground
  659. // and press the button
  660.  
  661. #if defined(CONFIG_KEYBOARD_GPIO_POLLED)|| defined(CONFIG_KEYBOARD_GPIO_MODULE)
  662. #include <linux/gpio_keys.h>
  663. #include <linux/input.h>
  664. #define BCM2708_KEYS_DEBOUNCE 5
  665.  
  666. static struct gpio_keys_button bcm2708_gpio_keys_table[] = {
  667.  
  668.         {
  669.                 .type           = EV_KEY,
  670.                 .code           = KEY_ENTER,
  671.                 .gpio           = 4,
  672.                 .active_low     = 1,
  673.                 .desc           = "gpio-keys: enter",
  674.                 .debounce_interval      = BCM2708_KEYS_DEBOUNCE,
  675.         }, {
  676.                 .type           = EV_KEY,
  677.                 .code           = KEY_A,
  678.                 .gpio           = 17,
  679.                 .active_low     = 1,
  680.                 .desc           = "gpio-keys: A",
  681.                 .debounce_interval      = BCM2708_KEYS_DEBOUNCE,
  682.         }, {
  683.                 .type           = EV_KEY,
  684.                 .code           = KEY_B,
  685.                 .gpio           = 21,
  686.                 .active_low     = 1,
  687.                 .desc           = "gpio-keys: B",
  688.                 .debounce_interval      = BCM2708_KEYS_DEBOUNCE,
  689.         }, {
  690.                 .type           = EV_KEY,
  691.                 .code           = KEY_C,
  692.                 .gpio           = 22,
  693.                 .active_low     = 1,
  694.                 .desc           = "gpio-keys: C",
  695.                 .debounce_interval      = BCM2708_KEYS_DEBOUNCE,
  696.         },
  697. };
  698.  
  699. static struct gpio_keys_platform_data bcm2708_gpio_keys_data = {
  700.         .buttons        = bcm2708_gpio_keys_table,
  701.         .nbuttons       = ARRAY_SIZE(bcm2708_gpio_keys_table),
  702.         .poll_interval  = 20
  703. };
  704.  
  705. static struct platform_device bcm2708_device_gpio_keys = {
  706.         .name           = "gpio-keys-polled",
  707.         .dev            = {
  708.                            .platform_data = &bcm2708_gpio_keys_data,
  709. },
  710. };
  711.  
  712.  
  713. static void __init bcm2708_init_gpio_keys(void)
  714. {
  715.         platform_device_register(&bcm2708_device_gpio_keys);
  716. }
  717. #else
  718. static inline void bcm2708_init_gpio_keys(void)
  719. {
  720. }
  721. #endif
  722.  
  723. // Reggie added, as a gpio-mouse proof of concept
  724. // ugly choice of gpio right now, it will either break or be broken by
  725. // i2c/spi drivers probably, it also needs proper intialisation as inputs etc.
  726. // and pullups enabled would be grrrrreat!
  727. // although if I understand the datasheet, all of the gpio are initialised as inputs with
  728. // pullups disabled, tx/rx are the only pins that are set to an alt-function, so we can
  729. // either set pullups in the init code, or tie each gpio pin to 3.3v via a 10k resistor?
  730. // SCL/SDA have physical 1.8k pullups on them, so perhaps 10k might be the wrong choice for
  731. // pullups on the other gpio?  using external resistors on the mouse/key inputs means the
  732. // gpio can be reused without any effort from the user
  733. // you should be able to hookup a joystick to the corresponding gpio pins, other side to ground, inputs should be active low
  734. // another way would be to use an arduino and a ps2 library, plug in a mouse, convert the x/y data to just output a low single
  735. // when appropriate to the gpio's, same method could be used to implement a keyboard via gpio but that would need
  736. // port expanders to implement a full 101 key keyboard
  737. // you could probably implement a 8x8 matrix keyboard, say 50 or so seperate keys + modifiers with the 16 gpio
  738. // on the pi but of course you'd be giving up all of the i2c, spi, uart pins. so an i2c/spi port expander would be
  739. // the right way to go, there are code examples in the kernel of this being implemented if someone wants to investigate
  740. // gpio/pin on the gpio header
  741. // 18 = 12
  742. // 23 = 16
  743. // 24 = 18
  744. // 25 = 22
  745. //  7 = 26
  746. //  8 = 24
  747. //  9 = 21
  748. #if defined(CONFIG_MOUSE_GPIO)|| defined(CONFIG_MOUSE_GPIO_MODULE)
  749. #include <linux/gpio_mouse.h>
  750. #include <linux/input.h>
  751. static struct gpio_mouse_platform_data gpio_mouse_data = {
  752.                 .scan_ms = 10,
  753.                 .polarity = GPIO_MOUSE_POLARITY_ACT_LOW, //active low
  754.                 {
  755.       {
  756.         .up = 18,
  757.         .down = 23,
  758.         .left = 24,
  759.         .right = 25,
  760.         .bleft = 7,
  761.         .bmiddle = 8,
  762.         .bright = 9,
  763.       },
  764.     },
  765. };
  766.  
  767. static struct platform_device bcm2708_device_gpio_mouse = {
  768.   .name = "gpio_mouse",
  769.   .id   = 0,
  770.   .dev  = {
  771.     .platform_data = &gpio_mouse_data,
  772.     },
  773. };
  774.  
  775. static void __init bcm2708_init_gpio_mouse(void)
  776. {
  777.         platform_device_register(&bcm2708_device_gpio_mouse);
  778. }
  779. #else
  780. static inline void bcm2708_init_gpio_mouse(void)
  781. {
  782. }
  783. #endif
  784.  
  785.  
  786.  
  787. MACHINE_START(BCM2708, "BCM2708")
  788.     /* Maintainer: Broadcom Europe Ltd. */
  789.     .map_io = bcm2708_map_io,.init_irq = bcm2708_init_irq,.timer =
  790.     &bcm2708_timer,.init_machine =
  791.     bcm2708_init, MACHINE_END module_param(boardrev, uint, 0644);
  792. module_param(serial, uint, 0644);
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top