]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control-pxmc.git/blob - src/app/rpi-pmsm-test1/rpi_gpclk.c
RPi PXMC Test: preliminary preparations for compatibility with RTEMS.
[fpga/rpi-motor-control-pxmc.git] / src / app / rpi-pmsm-test1 / rpi_gpclk.c
1 /**
2  * (C) 2015 by Martin Prudek prudemar@fel.cvut.cz
3  * (C) 2015 by Pavel Pisa pisa@cmp.felk.cvut.cz
4  *
5  * Configuration of the General Purpose Clocks outputs
6  * Inspired by wiringPi written by Gordon Henderson.
7  */
8
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <stdint.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <time.h>
18 #include <fcntl.h>
19 #include <pthread.h>
20 #include <sys/time.h>
21 #include <sys/mman.h>
22 #include <sys/stat.h>
23 #include <sys/wait.h>
24 #include <sys/ioctl.h>
25
26 #include "rpi_gpio.h"
27 #include "rpi_gpclk.h"
28
29 #define CLK_GPx_CTL(chan) \
30   (rpi_registers_mapping.clk_base[28 + 2 * (chan)])
31
32 #define CLK_GPx_DIV(chan) \
33   (rpi_registers_mapping.clk_base[29 + 2 * (chan)])
34
35 #define CLK_CTL_SRC_OSC  1  /* 19.2 MHz */
36 #define CLK_CTL_SRC_PLLC 5  /* 1000 MHz */
37 #define CLK_CTL_SRC_PLLD 6  /*  500 MHz */
38 #define CLK_CTL_SRC_HDMI 7  /*  216 MHz */
39
40 #define CLK_PASSWD  (0x5A<<24)
41 #define CLK_CTL_MASH(x)((x)<<9)
42 #define CLK_CTL_BUSY    (1 <<7)
43 #define CLK_CTL_KILL    (1 <<5)
44 #define CLK_CTL_ENAB    (1 <<4)
45 #define CLK_CTL_SRC(x) ((x)<<0)
46
47 #define CLK_DIV_DIVI(x) ((x)<<12)
48 #define CLK_DIV_DIVF(x) ((x)<< 0)
49
50 uint32_t rpi_gpclk_src_to_reg[] = {
51     [RPI_GPCLK_PLLD_500_MHZ] = CLK_CTL_SRC_PLLD,
52     [RPI_GPCLK_OSC_19_MHZ_2] = CLK_CTL_SRC_OSC,
53     [RPI_GPCLK_HDMI_216_MHZ] = CLK_CTL_SRC_HDMI,
54     [RPI_GPCLK_PLLC_1000_MHZ] = CLK_CTL_SRC_PLLD,
55 };
56
57 int rpi_gpclk_setup(int chan, int source, int div_int, int div_frac)
58 {
59     int MASH = 0;
60     uint32_t clksrc;
61
62     if (!rpi_registers_mapping.mapping_initialized)
63         return -1;
64
65     if ((source < 0) || (source > sizeof(rpi_gpclk_src_to_reg) /
66          sizeof(*rpi_gpclk_src_to_reg) ))
67         return -2;
68
69     if ((div_int  < 2) || (div_int   > 4095))
70         return -3;
71
72     if ((div_frac < 0) || (div_frac  > 4095))
73         return -4;
74
75     if ((MASH   < 0) || (MASH   > 3))
76         return -5;
77
78     clksrc = rpi_gpclk_src_to_reg[source];
79
80     CLK_GPx_CTL(chan) = CLK_PASSWD | CLK_CTL_KILL;
81
82     while (CLK_GPx_CTL(chan) & CLK_CTL_BUSY){
83         usleep(10);
84     }
85
86     CLK_GPx_DIV(chan) = (CLK_PASSWD | CLK_DIV_DIVI(div_int) | CLK_DIV_DIVF(div_frac));
87
88     usleep(10);
89
90     CLK_GPx_CTL(chan) = (CLK_PASSWD | CLK_CTL_MASH(MASH) | CLK_CTL_SRC(clksrc));
91
92     usleep(10);
93
94     CLK_GPx_CTL(chan) |= (CLK_PASSWD | CLK_CTL_ENAB);
95
96     return 0;
97 }