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