162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/mach-dove/mpp.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * MPP functions for Marvell Dove SoCs 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/gpio.h> 1062306a36Sopenharmony_ci#include <linux/io.h> 1162306a36Sopenharmony_ci#include <plat/mpp.h> 1262306a36Sopenharmony_ci#include <plat/orion-gpio.h> 1362306a36Sopenharmony_ci#include "dove.h" 1462306a36Sopenharmony_ci#include "mpp.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct dove_mpp_grp { 1762306a36Sopenharmony_ci int start; 1862306a36Sopenharmony_ci int end; 1962306a36Sopenharmony_ci}; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* Map a group to a range of GPIO pins in that group */ 2262306a36Sopenharmony_cistatic const struct dove_mpp_grp dove_mpp_grp[] = { 2362306a36Sopenharmony_ci [MPP_24_39] = { 2462306a36Sopenharmony_ci .start = 24, 2562306a36Sopenharmony_ci .end = 39, 2662306a36Sopenharmony_ci }, 2762306a36Sopenharmony_ci [MPP_40_45] = { 2862306a36Sopenharmony_ci .start = 40, 2962306a36Sopenharmony_ci .end = 45, 3062306a36Sopenharmony_ci }, 3162306a36Sopenharmony_ci [MPP_46_51] = { 3262306a36Sopenharmony_ci .start = 46, 3362306a36Sopenharmony_ci .end = 51, 3462306a36Sopenharmony_ci }, 3562306a36Sopenharmony_ci [MPP_58_61] = { 3662306a36Sopenharmony_ci .start = 58, 3762306a36Sopenharmony_ci .end = 61, 3862306a36Sopenharmony_ci }, 3962306a36Sopenharmony_ci [MPP_62_63] = { 4062306a36Sopenharmony_ci .start = 62, 4162306a36Sopenharmony_ci .end = 63, 4262306a36Sopenharmony_ci }, 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* Enable gpio for a range of pins. mode should be a combination of 4662306a36Sopenharmony_ci GPIO_OUTPUT_OK | GPIO_INPUT_OK */ 4762306a36Sopenharmony_cistatic void __init dove_mpp_gpio_mode(int start, int end, int gpio_mode) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci int i; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci for (i = start; i <= end; i++) 5262306a36Sopenharmony_ci orion_gpio_set_valid(i, gpio_mode); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* Dump all the extra MPP registers. The platform code will dump the 5662306a36Sopenharmony_ci registers for pins 0-23. */ 5762306a36Sopenharmony_cistatic void __init dove_mpp_dump_regs(void) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci pr_debug("PMU_CTRL4_CTRL: %08x\n", 6062306a36Sopenharmony_ci readl(DOVE_MPP_CTRL4_VIRT_BASE)); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n", 6362306a36Sopenharmony_ci readl(DOVE_PMU_MPP_GENERAL_CTRL)); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE)); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic void __init dove_mpp_cfg_nfc(int sel) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci mpp_gen_cfg &= ~0x1; 7362306a36Sopenharmony_ci mpp_gen_cfg |= sel; 7462306a36Sopenharmony_ci writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void __init dove_mpp_cfg_au1(int sel) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); 8262306a36Sopenharmony_ci u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1); 8362306a36Sopenharmony_ci u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE); 8462306a36Sopenharmony_ci u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL); 8762306a36Sopenharmony_ci ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1); 8862306a36Sopenharmony_ci mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN); 8962306a36Sopenharmony_ci global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (!sel || sel == 0x2) 9262306a36Sopenharmony_ci dove_mpp_gpio_mode(52, 57, 0); 9362306a36Sopenharmony_ci else 9462306a36Sopenharmony_ci dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (sel & 0x1) { 9762306a36Sopenharmony_ci global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO; 9862306a36Sopenharmony_ci dove_mpp_gpio_mode(56, 57, 0); 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci if (sel & 0x2) { 10162306a36Sopenharmony_ci mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN; 10262306a36Sopenharmony_ci dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci if (sel & 0x4) { 10562306a36Sopenharmony_ci ssp_ctrl1 |= DOVE_SSP_ON_AU1; 10662306a36Sopenharmony_ci dove_mpp_gpio_mode(52, 55, 0); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci if (sel & 0x8) 10962306a36Sopenharmony_ci mpp_ctrl4 |= DOVE_AU1_GPIO_SEL; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE); 11262306a36Sopenharmony_ci writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1); 11362306a36Sopenharmony_ci writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE); 11462306a36Sopenharmony_ci writel(global_cfg_2, DOVE_GLOBAL_CONFIG_2); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* Configure the group registers, enabling GPIO if sel indicates the 11862306a36Sopenharmony_ci pin is to be used for GPIO */ 11962306a36Sopenharmony_cistatic void __init dove_mpp_conf_grp(unsigned int *mpp_grp_list) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); 12262306a36Sopenharmony_ci int gpio_mode; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci for ( ; *mpp_grp_list; mpp_grp_list++) { 12562306a36Sopenharmony_ci unsigned int num = MPP_NUM(*mpp_grp_list); 12662306a36Sopenharmony_ci unsigned int sel = MPP_SEL(*mpp_grp_list); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if (num > MPP_GRP_MAX) { 12962306a36Sopenharmony_ci pr_err("dove: invalid MPP GRP number (%u)\n", num); 13062306a36Sopenharmony_ci continue; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci mpp_ctrl4 &= ~(0x1 << num); 13462306a36Sopenharmony_ci mpp_ctrl4 |= sel << num; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0; 13762306a36Sopenharmony_ci dove_mpp_gpio_mode(dove_mpp_grp[num].start, 13862306a36Sopenharmony_ci dove_mpp_grp[num].end, gpio_mode); 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE); 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* Configure the various MPP pins on Dove */ 14462306a36Sopenharmony_civoid __init dove_mpp_conf(unsigned int *mpp_list, 14562306a36Sopenharmony_ci unsigned int *mpp_grp_list, 14662306a36Sopenharmony_ci unsigned int grp_au1_52_57, 14762306a36Sopenharmony_ci unsigned int grp_nfc_64_71) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci dove_mpp_dump_regs(); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Use platform code for pins 0-23 */ 15262306a36Sopenharmony_ci orion_mpp_conf(mpp_list, 0, MPP_MAX, DOVE_MPP_VIRT_BASE); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci dove_mpp_conf_grp(mpp_grp_list); 15562306a36Sopenharmony_ci dove_mpp_cfg_au1(grp_au1_52_57); 15662306a36Sopenharmony_ci dove_mpp_cfg_nfc(grp_nfc_64_71); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci dove_mpp_dump_regs(); 15962306a36Sopenharmony_ci} 160