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