]> git.sesse.net Git - pistorm/blob - gpio/gpio.c
Some random cleanup
[pistorm] / gpio / gpio.c
1 #include <stdint.h>
2 #include <stddef.h>
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <signal.h>
7 #include <fcntl.h>
8 #include <sys/mman.h>
9 #include <sys/ioctl.h>
10 #include "../m68k.h"
11 #include "gpio.h"
12 #include "../platforms/amiga/Gayle.h"
13
14 // I/O access
15 volatile unsigned int *gpio;
16 volatile unsigned int *gpclk;
17 volatile unsigned int gpfsel0;
18 volatile unsigned int gpfsel1;
19 volatile unsigned int gpfsel2;
20 volatile unsigned int gpfsel0_o;
21 volatile unsigned int gpfsel1_o;
22 volatile unsigned int gpfsel2_o;
23
24 volatile uint16_t srdata;
25 volatile uint32_t srdata2;
26 volatile uint32_t srdata2_old;
27
28 extern int mem_fd, mouse_fd, keyboard_fd;
29 extern int mem_fd_gpclk;
30
31 void *gpio_map;
32 void *gpclk_map;
33
34 unsigned char toggle;
35
36 static int g = 0;
37
38 inline void write16(uint32_t address, uint32_t data) {
39   uint32_t addr_h_s = (address & 0x0000ffff) << 8;
40   uint32_t addr_h_r = (~address & 0x0000ffff) << 8;
41   uint32_t addr_l_s = (address >> 16) << 8;
42   uint32_t addr_l_r = (~address >> 16) << 8;
43   uint32_t data_s = (data & 0x0000ffff) << 8;
44   uint32_t data_r = (~data & 0x0000ffff) << 8;
45
46   //      asm volatile ("dmb" ::: "memory");
47   W16
48   *(gpio) = gpfsel0_o;
49   *(gpio + 1) = gpfsel1_o;
50   *(gpio + 2) = gpfsel2_o;
51
52   *(gpio + 7) = addr_h_s;
53   *(gpio + 10) = addr_h_r;
54   GPIO_CLR = 1 << 7;
55   GPIO_SET = 1 << 7;
56
57   *(gpio + 7) = addr_l_s;
58   *(gpio + 10) = addr_l_r;
59   GPIO_CLR = 1 << 7;
60   GPIO_SET = 1 << 7;
61
62   // write phase
63   *(gpio + 7) = data_s;
64   *(gpio + 10) = data_r;
65   GPIO_CLR = 1 << 7;
66   GPIO_SET = 1 << 7;
67
68   *(gpio) = gpfsel0;
69   *(gpio + 1) = gpfsel1;
70   *(gpio + 2) = gpfsel2;
71   while ((GET_GPIO(0)))
72     ;
73   //     asm volatile ("dmb" ::: "memory");
74 }
75
76 inline void write8(uint32_t address, uint32_t data) {
77   if ((address & 1) == 0)
78     data = data + (data << 8);  // EVEN, A0=0,UDS
79   else
80     data = data & 0xff;  // ODD , A0=1,LDS
81   uint32_t addr_h_s = (address & 0x0000ffff) << 8;
82   uint32_t addr_h_r = (~address & 0x0000ffff) << 8;
83   uint32_t addr_l_s = (address >> 16) << 8;
84   uint32_t addr_l_r = (~address >> 16) << 8;
85   uint32_t data_s = (data & 0x0000ffff) << 8;
86   uint32_t data_r = (~data & 0x0000ffff) << 8;
87
88   //   asm volatile ("dmb" ::: "memory");
89   W8
90   *(gpio) = gpfsel0_o;
91   *(gpio + 1) = gpfsel1_o;
92   *(gpio + 2) = gpfsel2_o;
93
94   *(gpio + 7) = addr_h_s;
95   *(gpio + 10) = addr_h_r;
96   GPIO_CLR = 1 << 7;
97   GPIO_SET = 1 << 7;
98
99   *(gpio + 7) = addr_l_s;
100   *(gpio + 10) = addr_l_r;
101   GPIO_CLR = 1 << 7;
102   GPIO_SET = 1 << 7;
103
104   // write phase
105   *(gpio + 7) = data_s;
106   *(gpio + 10) = data_r;
107   GPIO_CLR = 1 << 7;
108   GPIO_SET = 1 << 7;
109
110   *(gpio) = gpfsel0;
111   *(gpio + 1) = gpfsel1;
112   *(gpio + 2) = gpfsel2;
113   while ((GET_GPIO(0)))
114     ;
115   //   asm volatile ("dmb" ::: "memory");
116 }
117
118 inline uint32_t read16(uint32_t address) {
119   volatile int val;
120   uint32_t addr_h_s = (address & 0x0000ffff) << 8;
121   uint32_t addr_h_r = (~address & 0x0000ffff) << 8;
122   uint32_t addr_l_s = (address >> 16) << 8;
123   uint32_t addr_l_r = (~address >> 16) << 8;
124
125   //   asm volatile ("dmb" ::: "memory");
126   R16
127   *(gpio) = gpfsel0_o;
128   *(gpio + 1) = gpfsel1_o;
129   *(gpio + 2) = gpfsel2_o;
130
131   *(gpio + 7) = addr_h_s;
132   *(gpio + 10) = addr_h_r;
133   GPIO_CLR = 1 << 7;
134   GPIO_SET = 1 << 7;
135
136   *(gpio + 7) = addr_l_s;
137   *(gpio + 10) = addr_l_r;
138   GPIO_CLR = 1 << 7;
139   GPIO_SET = 1 << 7;
140
141   // read phase
142   *(gpio) = gpfsel0;
143   *(gpio + 1) = gpfsel1;
144   *(gpio + 2) = gpfsel2;
145   GPIO_CLR = 1 << 6;
146   while (!(GET_GPIO(0)))
147     ;
148   GPIO_CLR = 1 << 6;
149   val = *(gpio + 13);
150   GPIO_SET = 1 << 6;
151   //    asm volatile ("dmb" ::: "memory");
152   return (val >> 8) & 0xffff;
153 }
154
155 inline uint32_t read8(uint32_t address) {
156   int val;
157   uint32_t addr_h_s = (address & 0x0000ffff) << 8;
158   uint32_t addr_h_r = (~address & 0x0000ffff) << 8;
159   uint32_t addr_l_s = (address >> 16) << 8;
160   uint32_t addr_l_r = (~address >> 16) << 8;
161
162   //    asm volatile ("dmb" ::: "memory");
163   R8
164   *(gpio) = gpfsel0_o;
165   *(gpio + 1) = gpfsel1_o;
166   *(gpio + 2) = gpfsel2_o;
167
168   *(gpio + 7) = addr_h_s;
169   *(gpio + 10) = addr_h_r;
170   GPIO_CLR = 1 << 7;
171   GPIO_SET = 1 << 7;
172
173   *(gpio + 7) = addr_l_s;
174   *(gpio + 10) = addr_l_r;
175   GPIO_CLR = 1 << 7;
176   GPIO_SET = 1 << 7;
177
178   // read phase
179   *(gpio) = gpfsel0;
180   *(gpio + 1) = gpfsel1;
181   *(gpio + 2) = gpfsel2;
182
183   GPIO_CLR = 1 << 6;
184   while (!(GET_GPIO(0)))
185     ;
186   GPIO_CLR = 1 << 6;
187   val = *(gpio + 13);
188   GPIO_SET = 1 << 6;
189   //    asm volatile ("dmb" ::: "memory");
190
191   val = (val >> 8) & 0xffff;
192   if ((address & 1) == 0)
193     return (val >> 8) & 0xff;  // EVEN, A0=0,UDS
194   else
195     return val & 0xff;  // ODD , A0=1,LDS
196 }
197
198 /******************************************************/
199
200 void write_reg(unsigned int value) {
201   STATUSREGADDR
202   *(gpio) = gpfsel0_o;
203   *(gpio + 1) = gpfsel1_o;
204   *(gpio + 2) = gpfsel2_o;
205   *(gpio + 7) = (value & 0xffff) << 8;
206   *(gpio + 10) = (~value & 0xffff) << 8;
207   GPIO_CLR = 1 << 7;
208   GPIO_CLR = 1 << 7;  // delay
209   GPIO_SET = 1 << 7;
210   GPIO_SET = 1 << 7;
211   // Bus HIGH-Z
212   *(gpio) = gpfsel0;
213   *(gpio + 1) = gpfsel1;
214   *(gpio + 2) = gpfsel2;
215 }
216
217 uint16_t read_reg(void) {
218   uint32_t val;
219   STATUSREGADDR
220   // Bus HIGH-Z
221   *(gpio) = gpfsel0;
222   *(gpio + 1) = gpfsel1;
223   *(gpio + 2) = gpfsel2;
224   GPIO_CLR = 1 << 6;
225   GPIO_CLR = 1 << 6;  // delay
226   GPIO_CLR = 1 << 6;
227   GPIO_CLR = 1 << 6;
228   val = *(gpio + 13);
229   GPIO_SET = 1 << 6;
230   return (uint16_t)(val >> 8);
231 }
232
233 //
234 // Set up a memory regions to access GPIO
235 //
236 void setup_io() {
237   /* open /dev/mem */
238   if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
239     printf("can't open /dev/mem \n");
240     exit(-1);
241   }
242
243   /* mmap GPIO */
244   gpio_map = mmap(
245       NULL,                    // Any adddress in our space will do
246       BCM2708_PERI_SIZE,       // Map length
247       PROT_READ | PROT_WRITE,  // Enable reading & writting to mapped memory
248       MAP_SHARED,              // Shared with other processes
249       mem_fd,                  // File to map
250       BCM2708_PERI_BASE        // Offset to GPIO peripheral
251   );
252
253   close(mem_fd);  // No need to keep mem_fd open after mmap
254
255   if (gpio_map == MAP_FAILED) {
256     printf("gpio mmap error %d\n", (int)gpio_map);  // errno also set!
257     exit(-1);
258   }
259
260   gpio = ((volatile unsigned *)gpio_map) + GPIO_ADDR / 4;
261   gpclk = ((volatile unsigned *)gpio_map) + GPCLK_ADDR / 4;
262
263 }  // setup_io
264
265 void gpio_enable_200mhz() {
266   *(gpclk + (CLK_GP0_CTL / 4)) = CLK_PASSWD | (1 << 5);
267   usleep(10);
268   while ((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7))
269     ;
270   usleep(100);
271   *(gpclk + (CLK_GP0_DIV / 4)) =
272       CLK_PASSWD | (6 << 12);  // divider , 6=200MHz on pi3
273   usleep(10);
274   *(gpclk + (CLK_GP0_CTL / 4)) =
275       CLK_PASSWD | 5 | (1 << 4);  // pll? 6=plld, 5=pllc
276   usleep(10);
277   while (((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7)) == 0)
278     ;
279   usleep(100);
280
281   SET_GPIO_ALT(4, 0);  // gpclk0
282
283   // set SA to output
284   INP_GPIO(2);
285   OUT_GPIO(2);
286   INP_GPIO(3);
287   OUT_GPIO(3);
288   INP_GPIO(5);
289   OUT_GPIO(5);
290
291   // set gpio0 (aux0) and gpio1 (aux1) to input
292   INP_GPIO(0);
293   INP_GPIO(1);
294
295   // Set GPIO pins 6,7 and 8-23 to output
296   for (g = 6; g <= 23; g++) {
297     INP_GPIO(g);
298     OUT_GPIO(g);
299   }
300   printf("Precalculate GPIO8-23 as Output\n");
301   gpfsel0_o = *(gpio);  // store gpio ddr
302   printf("gpfsel0: %#x\n", gpfsel0_o);
303   gpfsel1_o = *(gpio + 1);  // store gpio ddr
304   printf("gpfsel1: %#x\n", gpfsel1_o);
305   gpfsel2_o = *(gpio + 2);  // store gpio ddr
306   printf("gpfsel2: %#x\n", gpfsel2_o);
307
308   // Set GPIO pins 8-23 to input
309   for (g = 8; g <= 23; g++) {
310     INP_GPIO(g);
311   }
312   printf("Precalculate GPIO8-23 as Input\n");
313   gpfsel0 = *(gpio);  // store gpio ddr
314   printf("gpfsel0: %#x\n", gpfsel0);
315   gpfsel1 = *(gpio + 1);  // store gpio ddr
316   printf("gpfsel1: %#x\n", gpfsel1);
317   gpfsel2 = *(gpio + 2);  // store gpio ddr
318   printf("gpfsel2: %#x\n", gpfsel2);
319
320   GPIO_CLR = 1 << 2;
321   GPIO_CLR = 1 << 3;
322   GPIO_SET = 1 << 5;
323
324   GPIO_SET = 1 << 6;
325   GPIO_SET = 1 << 7;
326 }
327
328 void gpio_handle_irq() {
329   if (GET_GPIO(1) == 0) {
330     srdata = read_reg();
331     m68k_set_irq((srdata >> 13) & 0xff);
332   } else {
333     if (CheckIrq() == 1) {
334       write16(0xdff09c, 0x8008);
335       m68k_set_irq(2);
336     }
337     else
338         m68k_set_irq(0);
339   };
340 }
341
342 void *iplThread(void *args) {
343   printf("IPL thread running/n");
344
345   while (42) {
346
347     if (GET_GPIO(1) == 0) {
348       toggle = 1;
349       m68k_end_timeslice();
350    //printf("thread!/n");
351     } else {
352       toggle = 0;
353     };
354     usleep(1);
355   }
356
357 }