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(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE); 75 76 dove_mpp_gpio_mode(64, 71, 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(52, 57, 0); 93 else 94 dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK); 95 96 if (sel & 0x1) { 97 global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO; 98 dove_mpp_gpio_mode(56, 57, 0); 99 } 100 if (sel & 0x2) { 101 mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN; 102 dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK); 103 } 104 if (sel & 0x4) { 105 ssp_ctrl1 |= DOVE_SSP_ON_AU1; 106 dove_mpp_gpio_mode(52, 55, 0); 107 } 108 if (sel & 0x8) 109 mpp_ctrl4 |= DOVE_AU1_GPIO_SEL; 110 111 writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE); 112 writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1); 113 writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE); 114 writel(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(dove_mpp_grp[num].start, 138 dove_mpp_grp[num].end, gpio_mode); 139 } 140 writel(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(grp_au1_52_57); 156 dove_mpp_cfg_nfc(grp_nfc_64_71); 157 158 dove_mpp_dump_regs(); 159 } 160
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.