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 valid and defined for the current IPA version? */ 13 static bool ipa_reg_valid(struct ipa *ipa, enum ipa_reg_id reg_id) 14 { 15 enum ipa_version version = ipa->version; 16 bool valid; 17 18 /* Check for bogus (out of range) register IDs */ 19 if ((u32)reg_id >= ipa->regs->reg_count) 20 return false; 21 22 switch (reg_id) { 23 case IPA_BCR: 24 case COUNTER_CFG: 25 valid = version < IPA_VERSION_4_5; 26 break; 27 28 case IPA_TX_CFG: 29 case FLAVOR_0: 30 case IDLE_INDICATION_CFG: 31 valid = version >= IPA_VERSION_3_5; 32 break; 33 34 case QTIME_TIMESTAMP_CFG: 35 case TIMERS_XO_CLK_DIV_CFG: 36 case TIMERS_PULSE_GRAN_CFG: 37 valid = version >= IPA_VERSION_4_5; 38 break; 39 40 case SRC_RSRC_GRP_45_RSRC_TYPE: 41 case DST_RSRC_GRP_45_RSRC_TYPE: 42 valid = version <= IPA_VERSION_3_1 || 43 version == IPA_VERSION_4_5; 44 break; 45 46 case SRC_RSRC_GRP_67_RSRC_TYPE: 47 case DST_RSRC_GRP_67_RSRC_TYPE: 48 valid = version <= IPA_VERSION_3_1; 49 break; 50 51 case ENDP_FILTER_ROUTER_HSH_CFG: 52 valid = version != IPA_VERSION_4_2; 53 break; 54 55 case IRQ_SUSPEND_EN: 56 case IRQ_SUSPEND_CLR: 57 valid = version >= IPA_VERSION_3_1; 58 break; 59 60 default: 61 valid = true; /* Others should be defined for all versions */ 62 break; 63 } 64 65 /* To be valid, it must be defined */ 66 67 return valid && ipa->regs->reg[reg_id]; 68 } 69 70 const struct ipa_reg *ipa_reg(struct ipa *ipa, enum ipa_reg_id reg_id) 71 { 72 if (WARN_ON(!ipa_reg_valid(ipa, reg_id))) 73 return NULL; 74 75 return ipa->regs->reg[reg_id]; 76 } 77 78 static const struct ipa_regs *ipa_regs(enum ipa_version version) 79 { 80 switch (version) { 81 case IPA_VERSION_3_1: 82 return &ipa_regs_v3_1; 83 case IPA_VERSION_3_5_1: 84 return &ipa_regs_v3_5_1; 85 case IPA_VERSION_4_2: 86 return &ipa_regs_v4_2; 87 case IPA_VERSION_4_5: 88 return &ipa_regs_v4_5; 89 case IPA_VERSION_4_7: 90 return &ipa_regs_v4_7; 91 case IPA_VERSION_4_9: 92 return &ipa_regs_v4_9; 93 case IPA_VERSION_4_11: 94 return &ipa_regs_v4_11; 95 default: 96 return NULL; 97 } 98 } 99 100 int ipa_reg_init(struct ipa *ipa) 101 { 102 struct device *dev = &ipa->pdev->dev; 103 const struct ipa_regs *regs; 104 struct resource *res; 105 106 regs = ipa_regs(ipa->version); 107 if (!regs) 108 return -EINVAL; 109 110 if (WARN_ON(regs->reg_count > IPA_REG_ID_COUNT)) 111 return -EINVAL; 112 113 /* Setup IPA register memory */ 114 res = platform_get_resource_byname(ipa->pdev, IORESOURCE_MEM, 115 "ipa-reg"); 116 if (!res) { 117 dev_err(dev, "DT error getting \"ipa-reg\" memory property\n"); 118 return -ENODEV; 119 } 120 121 ipa->reg_virt = ioremap(res->start, resource_size(res)); 122 if (!ipa->reg_virt) { 123 dev_err(dev, "unable to remap \"ipa-reg\" memory\n"); 124 return -ENOMEM; 125 } 126 ipa->reg_addr = res->start; 127 ipa->regs = regs; 128 129 return 0; 130 } 131 132 void ipa_reg_exit(struct ipa *ipa) 133 { 134 iounmap(ipa->reg_virt); 135 } 136