1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2013 Keymile AG 4 * Valentin Longchamp <valentin.longchamp@keymile.com> 5 */ 6 7 #include <common.h> 8 9 #include "../common/common.h" 10 #include "kmp204x.h" 11 12 /* QRIO GPIO register offsets */ 13 #define DIRECT_OFF 0x18 14 #define GPRT_OFF 0x1c 15 16 int qrio_get_gpio(u8 port_off, u8 gpio_nr) 17 { 18 u32 gprt; 19 20 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 21 22 gprt = in_be32(qrio_base + port_off + GPRT_OFF); 23 24 return (gprt >> gpio_nr) & 1U; 25 } 26 27 void qrio_set_gpio(u8 port_off, u8 gpio_nr, bool value) 28 { 29 u32 gprt, mask; 30 31 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 32 33 mask = 1U << gpio_nr; 34 35 gprt = in_be32(qrio_base + port_off + GPRT_OFF); 36 if (value) 37 gprt |= mask; 38 else 39 gprt &= ~mask; 40 41 out_be32(qrio_base + port_off + GPRT_OFF, gprt); 42 } 43 44 void qrio_gpio_direction_output(u8 port_off, u8 gpio_nr, bool value) 45 { 46 u32 direct, mask; 47 48 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 49 50 mask = 1U << gpio_nr; 51 52 direct = in_be32(qrio_base + port_off + DIRECT_OFF); 53 direct |= mask; 54 out_be32(qrio_base + port_off + DIRECT_OFF, direct); 55 56 qrio_set_gpio(port_off, gpio_nr, value); 57 } 58 59 void qrio_gpio_direction_input(u8 port_off, u8 gpio_nr) 60 { 61 u32 direct, mask; 62 63 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 64 65 mask = 1U << gpio_nr; 66 67 direct = in_be32(qrio_base + port_off + DIRECT_OFF); 68 direct &= ~mask; 69 out_be32(qrio_base + port_off + DIRECT_OFF, direct); 70 } 71 72 void qrio_set_opendrain_gpio(u8 port_off, u8 gpio_nr, u8 val) 73 { 74 u32 direct, mask; 75 76 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 77 78 mask = 1U << gpio_nr; 79 80 direct = in_be32(qrio_base + port_off + DIRECT_OFF); 81 if (val == 0) 82 /* set to output -> GPIO drives low */ 83 direct |= mask; 84 else 85 /* set to input -> GPIO floating */ 86 direct &= ~mask; 87 88 out_be32(qrio_base + port_off + DIRECT_OFF, direct); 89 } 90 91 #define WDMASK_OFF 0x16 92 93 void qrio_wdmask(u8 bit, bool wden) 94 { 95 u16 wdmask; 96 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 97 98 wdmask = in_be16(qrio_base + WDMASK_OFF); 99 100 if (wden) 101 wdmask |= (1 << bit); 102 else 103 wdmask &= ~(1 << bit); 104 105 out_be16(qrio_base + WDMASK_OFF, wdmask); 106 } 107 108 #define PRST_OFF 0x1a 109 110 void qrio_prst(u8 bit, bool en, bool wden) 111 { 112 u16 prst; 113 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 114 115 qrio_wdmask(bit, wden); 116 117 prst = in_be16(qrio_base + PRST_OFF); 118 119 if (en) 120 prst &= ~(1 << bit); 121 else 122 prst |= (1 << bit); 123 124 out_be16(qrio_base + PRST_OFF, prst); 125 } 126 127 #define PRSTCFG_OFF 0x1c 128 129 void qrio_prstcfg(u8 bit, u8 mode) 130 { 131 u32 prstcfg; 132 u8 i; 133 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 134 135 prstcfg = in_be32(qrio_base + PRSTCFG_OFF); 136 137 for (i = 0; i < 2; i++) { 138 if (mode & (1<<i)) 139 set_bit(2*bit+i, &prstcfg); 140 else 141 clear_bit(2*bit+i, &prstcfg); 142 } 143 144 out_be32(qrio_base + PRSTCFG_OFF, prstcfg); 145 } 146 147 #define CTRLH_OFF 0x02 148 #define CTRLH_WRL_BOOT 0x01 149 #define CTRLH_WRL_UNITRUN 0x02 150 151 void qrio_set_leds(void) 152 { 153 u8 ctrlh; 154 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 155 156 /* set UNIT LED to RED and BOOT LED to ON */ 157 ctrlh = in_8(qrio_base + CTRLH_OFF); 158 ctrlh |= (CTRLH_WRL_BOOT | CTRLH_WRL_UNITRUN); 159 out_8(qrio_base + CTRLH_OFF, ctrlh); 160 } 161 162 #define CTRLL_OFF 0x03 163 #define CTRLL_WRB_BUFENA 0x20 164 165 void qrio_enable_app_buffer(void) 166 { 167 u8 ctrll; 168 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 169 170 /* enable application buffer */ 171 ctrll = in_8(qrio_base + CTRLL_OFF); 172 ctrll |= (CTRLL_WRB_BUFENA); 173 out_8(qrio_base + CTRLL_OFF, ctrll); 174 } 175 176 #define REASON1_OFF 0x12 177 #define REASON1_CPUWD 0x01 178 179 void qrio_cpuwd_flag(bool flag) 180 { 181 u8 reason1; 182 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 183 reason1 = in_8(qrio_base + REASON1_OFF); 184 if (flag) 185 reason1 |= REASON1_CPUWD; 186 else 187 reason1 &= ~REASON1_CPUWD; 188 out_8(qrio_base + REASON1_OFF, reason1); 189 } 190 191 #define RSTCFG_OFF 0x11 192 193 void qrio_uprstreq(u8 mode) 194 { 195 u32 rstcfg; 196 void __iomem *qrio_base = (void *)CONFIG_SYS_QRIO_BASE; 197 198 rstcfg = in_8(qrio_base + RSTCFG_OFF); 199 200 if (mode & UPREQ_CORE_RST) 201 rstcfg |= UPREQ_CORE_RST; 202 else 203 rstcfg &= ~UPREQ_CORE_RST; 204 205 out_8(qrio_base + RSTCFG_OFF, rstcfg); 206 } 207