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_9: 90 return &ipa_regs_v4_9; 91 case IPA_VERSION_4_11: 92 return &ipa_regs_v4_11; 93 default: 94 return NULL; 95 } 96 } 97 98 int ipa_reg_init(struct ipa *ipa) 99 { 100 struct device *dev = &ipa->pdev->dev; 101 const struct ipa_regs *regs; 102 struct resource *res; 103 104 regs = ipa_regs(ipa->version); 105 if (!regs) 106 return -EINVAL; 107 108 if (WARN_ON(regs->reg_count > IPA_REG_ID_COUNT)) 109 return -EINVAL; 110 111 /* Setup IPA register memory */ 112 res = platform_get_resource_byname(ipa->pdev, IORESOURCE_MEM, 113 "ipa-reg"); 114 if (!res) { 115 dev_err(dev, "DT error getting \"ipa-reg\" memory property\n"); 116 return -ENODEV; 117 } 118 119 ipa->reg_virt = ioremap(res->start, resource_size(res)); 120 if (!ipa->reg_virt) { 121 dev_err(dev, "unable to remap \"ipa-reg\" memory\n"); 122 return -ENOMEM; 123 } 124 ipa->reg_addr = res->start; 125 ipa->regs = regs; 126 127 return 0; 128 } 129 130 void ipa_reg_exit(struct ipa *ipa) 131 { 132 iounmap(ipa->reg_virt); 133 } 134