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