1 // SPDX-License-Identifier: GPL-2.0 2 3 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. 4 * Copyright (C) 2019-2022 Linaro Ltd. 5 */ 6 7 #include <linux/io.h> 8 9 #include "ipa.h" 10 #include "ipa_reg.h" 11 12 /* Is this register ID valid for the current IPA version? */ 13 static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id) 14 { 15 enum ipa_version version = ipa->version; 16 17 switch (reg_id) { 18 case IPA_BCR: 19 case COUNTER_CFG: 20 return version < IPA_VERSION_4_5; 21 22 case IPA_TX_CFG: 23 case FLAVOR_0: 24 case IDLE_INDICATION_CFG: 25 return version >= IPA_VERSION_3_5; 26 27 case QTIME_TIMESTAMP_CFG: 28 case TIMERS_XO_CLK_DIV_CFG: 29 case TIMERS_PULSE_GRAN_CFG: 30 return version >= IPA_VERSION_4_5; 31 32 case SRC_RSRC_GRP_45_RSRC_TYPE: 33 case DST_RSRC_GRP_45_RSRC_TYPE: 34 return version <= IPA_VERSION_3_1 || 35 version == IPA_VERSION_4_5; 36 37 case SRC_RSRC_GRP_67_RSRC_TYPE: 38 case DST_RSRC_GRP_67_RSRC_TYPE: 39 return version <= IPA_VERSION_3_1; 40 41 case ENDP_FILTER_ROUTER_HSH_CFG: 42 return version != IPA_VERSION_4_2; 43 44 case IRQ_SUSPEND_EN: 45 case IRQ_SUSPEND_CLR: 46 return version >= IPA_VERSION_3_1; 47 48 case COMP_CFG: 49 case CLKON_CFG: 50 case ROUTE: 51 case SHARED_MEM_SIZE: 52 case QSB_MAX_WRITES: 53 case QSB_MAX_READS: 54 case FILT_ROUT_HASH_EN: 55 case FILT_ROUT_CACHE_CFG: 56 case FILT_ROUT_HASH_FLUSH: 57 case FILT_ROUT_CACHE_FLUSH: 58 case STATE_AGGR_ACTIVE: 59 case LOCAL_PKT_PROC_CNTXT: 60 case AGGR_FORCE_CLOSE: 61 case SRC_RSRC_GRP_01_RSRC_TYPE: 62 case SRC_RSRC_GRP_23_RSRC_TYPE: 63 case DST_RSRC_GRP_01_RSRC_TYPE: 64 case DST_RSRC_GRP_23_RSRC_TYPE: 65 case ENDP_INIT_CTRL: 66 case ENDP_INIT_CFG: 67 case ENDP_INIT_NAT: 68 case ENDP_INIT_HDR: 69 case ENDP_INIT_HDR_EXT: 70 case ENDP_INIT_HDR_METADATA_MASK: 71 case ENDP_INIT_MODE: 72 case ENDP_INIT_AGGR: 73 case ENDP_INIT_HOL_BLOCK_EN: 74 case ENDP_INIT_HOL_BLOCK_TIMER: 75 case ENDP_INIT_DEAGGR: 76 case ENDP_INIT_RSRC_GRP: 77 case ENDP_INIT_SEQ: 78 case ENDP_STATUS: 79 case ENDP_FILTER_CACHE_CFG: 80 case ENDP_ROUTER_CACHE_CFG: 81 case IPA_IRQ_STTS: 82 case IPA_IRQ_EN: 83 case IPA_IRQ_CLR: 84 case IPA_IRQ_UC: 85 case IRQ_SUSPEND_INFO: 86 return true; /* These should be defined for all versions */ 87 88 default: 89 return false; 90 } 91 } 92 93 const struct reg *ipa_reg(struct ipa *ipa, enum ipa_reg_id reg_id) 94 { 95 if (WARN(!ipa_reg_id_valid(ipa, reg_id), "invalid reg %u\n", reg_id)) 96 return NULL; 97 98 return reg(ipa->regs, reg_id); 99 } 100 101 static const struct regs *ipa_regs(enum ipa_version version) 102 { 103 switch (version) { 104 case IPA_VERSION_3_1: 105 return &ipa_regs_v3_1; 106 case IPA_VERSION_3_5_1: 107 return &ipa_regs_v3_5_1; 108 case IPA_VERSION_4_2: 109 return &ipa_regs_v4_2; 110 case IPA_VERSION_4_5: 111 return &ipa_regs_v4_5; 112 case IPA_VERSION_4_7: 113 return &ipa_regs_v4_7; 114 case IPA_VERSION_4_9: 115 return &ipa_regs_v4_9; 116 case IPA_VERSION_4_11: 117 return &ipa_regs_v4_11; 118 default: 119 return NULL; 120 } 121 } 122 123 int ipa_reg_init(struct ipa *ipa) 124 { 125 struct device *dev = &ipa->pdev->dev; 126 const struct regs *regs; 127 struct resource *res; 128 129 regs = ipa_regs(ipa->version); 130 if (!regs) 131 return -EINVAL; 132 133 if (WARN_ON(regs->reg_count > IPA_REG_ID_COUNT)) 134 return -EINVAL; 135 136 /* Setup IPA register memory */ 137 res = platform_get_resource_byname(ipa->pdev, IORESOURCE_MEM, 138 "ipa-reg"); 139 if (!res) { 140 dev_err(dev, "DT error getting \"ipa-reg\" memory property\n"); 141 return -ENODEV; 142 } 143 144 ipa->reg_virt = ioremap(res->start, resource_size(res)); 145 if (!ipa->reg_virt) { 146 dev_err(dev, "unable to remap \"ipa-reg\" memory\n"); 147 return -ENOMEM; 148 } 149 ipa->regs = regs; 150 151 return 0; 152 } 153 154 void ipa_reg_exit(struct ipa *ipa) 155 { 156 iounmap(ipa->reg_virt); 157 } 158