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