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