1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * arch/arm/mach-dove/mpp.c |
4 | * |
5 | * MPP functions for Marvell Dove SoCs |
6 | */ |
7 | |
8 | #include <linux/kernel.h> |
9 | #include <linux/gpio.h> |
10 | #include <linux/io.h> |
11 | #include <plat/mpp.h> |
12 | #include <plat/orion-gpio.h> |
13 | #include "dove.h" |
14 | #include "mpp.h" |
15 | |
16 | struct dove_mpp_grp { |
17 | int start; |
18 | int end; |
19 | }; |
20 | |
21 | /* Map a group to a range of GPIO pins in that group */ |
22 | static const struct dove_mpp_grp dove_mpp_grp[] = { |
23 | [MPP_24_39] = { |
24 | .start = 24, |
25 | .end = 39, |
26 | }, |
27 | [MPP_40_45] = { |
28 | .start = 40, |
29 | .end = 45, |
30 | }, |
31 | [MPP_46_51] = { |
32 | .start = 46, |
33 | .end = 51, |
34 | }, |
35 | [MPP_58_61] = { |
36 | .start = 58, |
37 | .end = 61, |
38 | }, |
39 | [MPP_62_63] = { |
40 | .start = 62, |
41 | .end = 63, |
42 | }, |
43 | }; |
44 | |
45 | /* Enable gpio for a range of pins. mode should be a combination of |
46 | GPIO_OUTPUT_OK | GPIO_INPUT_OK */ |
47 | static void __init dove_mpp_gpio_mode(int start, int end, int gpio_mode) |
48 | { |
49 | int i; |
50 | |
51 | for (i = start; i <= end; i++) |
52 | orion_gpio_set_valid(i, gpio_mode); |
53 | } |
54 | |
55 | /* Dump all the extra MPP registers. The platform code will dump the |
56 | registers for pins 0-23. */ |
57 | static void __init dove_mpp_dump_regs(void) |
58 | { |
59 | pr_debug("PMU_CTRL4_CTRL: %08x\n" , |
60 | readl(DOVE_MPP_CTRL4_VIRT_BASE)); |
61 | |
62 | pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n" , |
63 | readl(DOVE_PMU_MPP_GENERAL_CTRL)); |
64 | |
65 | pr_debug("MPP_GENERAL: %08x\n" , readl(DOVE_MPP_GENERAL_VIRT_BASE)); |
66 | } |
67 | |
68 | static void __init dove_mpp_cfg_nfc(int sel) |
69 | { |
70 | u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE); |
71 | |
72 | mpp_gen_cfg &= ~0x1; |
73 | mpp_gen_cfg |= sel; |
74 | writel(val: mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE); |
75 | |
76 | dove_mpp_gpio_mode(start: 64, end: 71, gpio_mode: GPIO_OUTPUT_OK); |
77 | } |
78 | |
79 | static void __init dove_mpp_cfg_au1(int sel) |
80 | { |
81 | u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); |
82 | u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1); |
83 | u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE); |
84 | u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2); |
85 | |
86 | mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL); |
87 | ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1); |
88 | mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN); |
89 | global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO); |
90 | |
91 | if (!sel || sel == 0x2) |
92 | dove_mpp_gpio_mode(start: 52, end: 57, gpio_mode: 0); |
93 | else |
94 | dove_mpp_gpio_mode(start: 52, end: 57, gpio_mode: GPIO_OUTPUT_OK | GPIO_INPUT_OK); |
95 | |
96 | if (sel & 0x1) { |
97 | global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO; |
98 | dove_mpp_gpio_mode(start: 56, end: 57, gpio_mode: 0); |
99 | } |
100 | if (sel & 0x2) { |
101 | mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN; |
102 | dove_mpp_gpio_mode(start: 57, end: 57, gpio_mode: GPIO_OUTPUT_OK | GPIO_INPUT_OK); |
103 | } |
104 | if (sel & 0x4) { |
105 | ssp_ctrl1 |= DOVE_SSP_ON_AU1; |
106 | dove_mpp_gpio_mode(start: 52, end: 55, gpio_mode: 0); |
107 | } |
108 | if (sel & 0x8) |
109 | mpp_ctrl4 |= DOVE_AU1_GPIO_SEL; |
110 | |
111 | writel(val: mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE); |
112 | writel(val: ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1); |
113 | writel(val: mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE); |
114 | writel(val: global_cfg_2, DOVE_GLOBAL_CONFIG_2); |
115 | } |
116 | |
117 | /* Configure the group registers, enabling GPIO if sel indicates the |
118 | pin is to be used for GPIO */ |
119 | static void __init dove_mpp_conf_grp(unsigned int *mpp_grp_list) |
120 | { |
121 | u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); |
122 | int gpio_mode; |
123 | |
124 | for ( ; *mpp_grp_list; mpp_grp_list++) { |
125 | unsigned int num = MPP_NUM(*mpp_grp_list); |
126 | unsigned int sel = MPP_SEL(*mpp_grp_list); |
127 | |
128 | if (num > MPP_GRP_MAX) { |
129 | pr_err("dove: invalid MPP GRP number (%u)\n" , num); |
130 | continue; |
131 | } |
132 | |
133 | mpp_ctrl4 &= ~(0x1 << num); |
134 | mpp_ctrl4 |= sel << num; |
135 | |
136 | gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0; |
137 | dove_mpp_gpio_mode(start: dove_mpp_grp[num].start, |
138 | end: dove_mpp_grp[num].end, gpio_mode); |
139 | } |
140 | writel(val: mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE); |
141 | } |
142 | |
143 | /* Configure the various MPP pins on Dove */ |
144 | void __init dove_mpp_conf(unsigned int *mpp_list, |
145 | unsigned int *mpp_grp_list, |
146 | unsigned int grp_au1_52_57, |
147 | unsigned int grp_nfc_64_71) |
148 | { |
149 | dove_mpp_dump_regs(); |
150 | |
151 | /* Use platform code for pins 0-23 */ |
152 | orion_mpp_conf(mpp_list, 0, MPP_MAX, DOVE_MPP_VIRT_BASE); |
153 | |
154 | dove_mpp_conf_grp(mpp_grp_list); |
155 | dove_mpp_cfg_au1(sel: grp_au1_52_57); |
156 | dove_mpp_cfg_nfc(sel: grp_nfc_64_71); |
157 | |
158 | dove_mpp_dump_regs(); |
159 | } |
160 | |