]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control-pxmc.git/blob - src/app/rpi-pmsm-test1/rpi_gpio.c
cc9eeede64b392771a6f4f4386cd613e9e5c7918
[fpga/rpi-motor-control-pxmc.git] / src / app / rpi-pmsm-test1 / rpi_gpio.c
1 /*
2  * Bidirectional pwm_base on Raspberry Pi module
3  *
4  * Copyright (C) 2014 Pavel Pisa <pisa@cmp.felk.cvut.cz>
5  * Copyright (C) 2014 Radek Meciar
6  *
7  * Department of Control Engineering
8  * Faculty of Electrical Engineering
9  * Czech Technical University in Prague (CTU)
10  *
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
19  * although.
20  */
21
22 #include "rpi_gpio.h"
23
24 /*Based on bachelor thesis work Meciar Radek: Motor control with Raspberry Pi board and Linux*/
25
26 #include <fcntl.h>
27 #include <sys/mman.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <stdint.h>
31
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 */
36
37 #define PAGE_SIZE       (4*1024)
38 #define BLOCK_SIZE      (4*1024)
39
40 rpi_registers_mapping_t rpi_registers_mapping;
41
42 /* Based on infromation from: http://elinux.org/RPi_Low-level_peripherals */
43
44 static int rpi_gpio_fnc_setup(unsigned gpio, unsigned fnc)
45 {
46     volatile unsigned *reg;
47     unsigned mask;
48
49     if (gpio >= 32)
50         return -1;
51
52     mask = 7 << ((gpio % 10) * 3);
53     fnc = fnc << ((gpio % 10) * 3);
54     fnc &= mask;
55     reg = rpi_registers_mapping.gpio_base + (gpio /10);
56
57     if ((*reg & mask) != fnc) {
58       *reg &= ~mask;
59       *reg |= fnc;
60     }
61     return 0;
62 }
63
64 /* Configure gpio_base pin for input */
65 int rpi_gpio_direction_input(unsigned gpio)
66 {
67     return rpi_gpio_fnc_setup(gpio, 0);
68 }
69
70 /* Configure gpio_base pin for output */
71 int rpi_gpio_direction_output(unsigned gpio, int value)
72 {
73     if (gpio >= 32)
74         return -1;
75
76     rpi_gpio_set_value(gpio, value);
77     if (rpi_gpio_fnc_setup(gpio, 1) < 0)
78         return -1;
79     rpi_gpio_set_value(gpio, value);
80     return 0;
81 }
82
83 /* Configure gpio_base pin for alternate function */
84 int rpi_gpio_alt_fnc(unsigned gpio, int alt_fnc)
85 {
86     return rpi_gpio_fnc_setup(gpio, alt_fnc <= 3? alt_fnc + 4: alt_fnc == 4? 3: 2);
87 }
88
89 /*
90 peripheral_registers_map:
91
92 Maps registers into virtual address space and sets  *gpio_base, *pwm_base, *clk_base poiners
93 */
94 int rpi_peripheral_registers_map(void)
95 {
96     rpi_registers_mapping_t *rrmap = &rpi_registers_mapping;
97     if (rrmap->mapping_initialized)
98         return rrmap->mapping_initialized;
99
100     rrmap->mapping_initialized = -1;
101
102     if ((rrmap->mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
103         return -1;
104     }
105
106     rrmap->gpio_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, rrmap->mem_fd, GPIO_BASE);
107
108     if (rrmap->gpio_map == MAP_FAILED) {
109         return -1;
110     }
111
112     rrmap->gpio_base = (volatile unsigned *)rrmap->gpio_map;
113
114     rrmap->pwm_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, rrmap->mem_fd, PWM_BASE);
115
116     if (rrmap->pwm_map == MAP_FAILED) {
117         return -1;
118     }
119
120     rrmap->pwm_base = (volatile unsigned *)rrmap->pwm_map;
121
122     rrmap->clk_map = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, rrmap->mem_fd, CLK_BASE);
123
124     if (rrmap->clk_map == MAP_FAILED) {
125         return -1;
126     }
127
128     rrmap->clk_base = (volatile unsigned *)rrmap->clk_map;
129
130     close(rrmap->mem_fd);
131
132     rrmap->mapping_initialized = 1;
133
134     return rrmap->mapping_initialized;
135 } /* peripheral_registers_map */