rk2928&rk30&rk3066b: new iomux support
[firefly-linux-kernel-4.4.55.git] / arch / arm / plat-rk / iomux.c
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <mach/iomux.h>
4 #include <mach/gpio.h>
5 #include <asm/io.h>
6
7 #if 0
8 #define DBG(x...)       INFO(KERN_INFO x)
9 #else
10 #define DBG(x...)
11 #endif
12
13 #define INFO(x...)      printk(KERN_INFO x)
14
15 struct iomux_mode{
16         unsigned int mode:4,
17                      off:4,
18                      goff:4,
19                      bank:4,
20                      reserve:16;
21 };
22 struct union_mode{
23         union{
24                 struct iomux_mode mux;
25                 unsigned int mode;
26         };
27 };
28
29 static inline int mode_is_valid(unsigned int mode)
30 {
31         struct union_mode m;
32         
33         m.mode = mode;
34         if(mode == INVALID_MODE || m.mux.bank >= GPIO_BANKS)
35                 return 0;
36         else
37                 return 1;
38
39 }
40 int mode_to_gpio(unsigned int mode)
41 {
42         struct union_mode m;
43
44         if(!mode_is_valid(mode)){
45                 INFO("<%s> mode(0x%x) is invalid\n", __func__, mode);
46                 return INVALID_GPIO;
47         }
48
49         m.mode = mode;
50         return PIN_BASE + m.mux.bank * 32 + (m.mux.goff - 0x0A) * 8 + m.mux.off;
51 }
52
53 int gpio_to_mode(int gpio)
54 {
55         unsigned int off;
56         struct union_mode m;
57
58         if(!gpio_is_valid(gpio)){
59                 INFO("<%s> gpio(%d), is invalid\n", __func__, gpio);
60                 return INVALID_MODE;
61         }
62
63         off = gpio - PIN_BASE;
64         m.mux.bank = off/32;
65         m.mux.goff = (off%32)/8 + 0x0A;
66         m.mux.off = off%256;
67
68
69         if(!mode_is_valid(m.mode)){
70                 INFO("<%s> gpio(gpio%d_%x%d) is invalid\n", __func__, m.mux.bank, m.mux.goff, m.mux.off);
71                 return INVALID_MODE;
72         }
73
74         return m.mode;
75 }
76
77 #ifdef GRF_IOMUX_BASE
78 void iomux_set(unsigned int mode)
79 {
80         unsigned int v, addr, mask;
81         struct union_mode m;
82         
83         m.mode = mode;
84         if(!mode_is_valid(mode)){
85                 INFO("<%s> mode(0x%x) is invalid\n", __func__, mode);
86                 return;
87         }
88         mask = (m.mux.mode < 2)?1:3;
89         v = (m.mux.mode << (m.mux.off * 2)) + (mask << (m.mux.off * 2 + 16));
90         addr = (unsigned int)GRF_IOMUX_BASE + 16 * m.mux.bank + 4 * (m.mux.goff - 0x0A);
91
92         DBG("<%s> mode(0x%04x), reg_addr(0x%08x), set_value(0x%08x)\n", __func__, mode, addr, v);
93
94         writel_relaxed(v, (void *)addr);
95 }
96 #else
97 void iomux_set(unsigned int mode)
98 {
99         INFO("%s is not support\n", __func__);
100         return;
101 }
102 #endif
103 EXPORT_SYMBOL(iomux_set);
104
105 void iomux_set_gpio_mode(int gpio)
106 {
107         unsigned int mode;
108
109         mode = gpio_to_mode(gpio);
110         if(mode_is_valid(mode))
111                 iomux_set(mode);
112 }
113 EXPORT_SYMBOL(iomux_set_gpio_mode);
114
115
116