Advertisement
Guest User

pi gpio-keys and gpio-mouse

a guest
Jun 19th, 2012
3,820
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 21.33 KB | None | 0 0
  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);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement