2 * Bidirectional pwm_base on Raspberry Pi module
4 * Copyright (C) 2014 Pavel Pisa <pisa@cmp.felk.cvut.cz>
5 * Copyright (C) 2014 Radek Meciar
7 * Department of Control Engineering
8 * Faculty of Electrical Engineering
9 * Czech Technical University in Prague (CTU)
11 * Next exception is granted in addition to GPL.
12 * Instantiating or linking compiled version of this code
13 * to produce an application image/executable, does not
14 * by itself cause the resulting application image/executable
15 * to be covered by the GNU General Public License.
16 * This exception does not however invalidate any other reasons
17 * why the executable file might be covered by the GNU Public License.
18 * Publication of enhanced or derived S-function files is required
24 /*Based on bachelor thesis work Meciar Radek: Motor control with Raspberry Pi board and Linux*/
32 #define BASE 0x20000000 /* registers common base address */
33 #define GPIO_BASE (BASE + 0x200000) /* gpio_base registers base address */
34 #define PWM_BASE (BASE + 0x20C000) /* pwm_base registers base address */
35 #define CLK_BASE (BASE + 0x101000) /* clk_base register base address */
37 #define PAGE_SIZE (4*1024)
38 #define BLOCK_SIZE (4*1024)
40 rpi_registers_mapping_t rpi_registers_mapping;
42 /* Based on infromation from: http://elinux.org/RPi_Low-level_peripherals */
44 static int rpi_gpio_fnc_setup(unsigned gpio, unsigned fnc)
46 volatile unsigned *reg;
52 mask = 7 << ((gpio % 10) * 3);
53 fnc = fnc << ((gpio % 10) * 3);
55 reg = rpi_registers_mapping.gpio_base + (gpio /10);
57 if ((*reg & mask) != fnc) {
64 /* Configure gpio_base pin for input */
65 int rpi_gpio_direction_input(unsigned gpio)
67 return rpi_gpio_fnc_setup(gpio, 0);
70 /* Configure gpio_base pin for output */
71 int rpi_gpio_direction_output(unsigned gpio, int value)
76 rpi_gpio_set_value(gpio, value);
77 if (rpi_gpio_fnc_setup(gpio, 1) < 0)
79 rpi_gpio_set_value(gpio, value);
83 /* Configure gpio_base pin for alternate function */
84 int rpi_gpio_alt_fnc(unsigned gpio, int alt_fnc)
86 return rpi_gpio_fnc_setup(gpio, alt_fnc <= 3? alt_fnc + 4: alt_fnc == 4? 3: 2);
90 peripheral_registers_map:
92 Maps registers into virtual address space and sets *gpio_base, *pwm_base, *clk_base poiners
94 int rpi_peripheral_registers_map(void)
96 rpi_registers_mapping_t *rrmap = &rpi_registers_mapping;
97 if (rrmap->mapping_initialized)
98 return rrmap->mapping_initialized;
100 rrmap->mapping_initialized = -1;
102 if ((rrmap->mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
106 rrmap->gpio_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, rrmap->mem_fd, GPIO_BASE);
108 if (rrmap->gpio_map == MAP_FAILED) {
112 rrmap->gpio_base = (volatile unsigned *)rrmap->gpio_map;
114 rrmap->pwm_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, rrmap->mem_fd, PWM_BASE);
116 if (rrmap->pwm_map == MAP_FAILED) {
120 rrmap->pwm_base = (volatile unsigned *)rrmap->pwm_map;
122 rrmap->clk_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, rrmap->mem_fd, CLK_BASE);
124 if (rrmap->clk_map == MAP_FAILED) {
128 rrmap->clk_base = (volatile unsigned *)rrmap->clk_map;
130 close(rrmap->mem_fd);
132 rrmap->mapping_initialized = 1;
134 return rrmap->mapping_initialized;
135 } /* peripheral_registers_map */