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#include <asm/io.h> 9#include <linux/bitops.h> 10 11#include "common.h" 12#include "qrio.h" 13 14/* QRIO ID register offset */ 15#define ID_REV_OFF 0x00 16 17/* QRIO GPIO register offsets */ 18#define DIRECT_OFF 0x18 19#define GPRT_OFF 0x1c 20 21void show_qrio(void) 22{ 23 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 24 u16 id_rev = in_be16(qrio_base + ID_REV_OFF); 25 26 printf("QRIO: id = %u, revision = %u\n", 27 (id_rev >> 8) & 0xff, id_rev & 0xff); 28} 29 30#define SLFTEST_OFF 0x06 31 32bool qrio_get_selftest_pin(void) 33{ 34 u8 slftest; 35 36 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 37 38 slftest = in_8(qrio_base + SLFTEST_OFF); 39 40 return (slftest & 1) > 0; 41} 42 43#define BPRTH_OFF 0x04 44 45bool qrio_get_pgy_pres_pin(void) 46{ 47 u8 pgy_pres; 48 49 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 50 51 pgy_pres = in_8(qrio_base + BPRTH_OFF); 52 53 return (pgy_pres & 0x80) > 0; 54} 55 56int qrio_get_gpio(u8 port_off, u8 gpio_nr) 57{ 58 u32 gprt; 59 60 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 61 62 gprt = in_be32(qrio_base + port_off + GPRT_OFF); 63 64 return (gprt >> gpio_nr) & 1U; 65} 66 67void qrio_set_gpio(u8 port_off, u8 gpio_nr, bool value) 68{ 69 u32 gprt, mask; 70 71 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 72 73 mask = 1U << gpio_nr; 74 75 gprt = in_be32(qrio_base + port_off + GPRT_OFF); 76 if (value) 77 gprt |= mask; 78 else 79 gprt &= ~mask; 80 81 out_be32(qrio_base + port_off + GPRT_OFF, gprt); 82} 83 84void qrio_gpio_direction_output(u8 port_off, u8 gpio_nr, bool value) 85{ 86 u32 direct, mask; 87 88 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 89 90 mask = 1U << gpio_nr; 91 92 direct = in_be32(qrio_base + port_off + DIRECT_OFF); 93 direct |= mask; 94 out_be32(qrio_base + port_off + DIRECT_OFF, direct); 95 96 qrio_set_gpio(port_off, gpio_nr, value); 97} 98 99void qrio_gpio_direction_input(u8 port_off, u8 gpio_nr) 100{ 101 u32 direct, mask; 102 103 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 104 105 mask = 1U << gpio_nr; 106 107 direct = in_be32(qrio_base + port_off + DIRECT_OFF); 108 direct &= ~mask; 109 out_be32(qrio_base + port_off + DIRECT_OFF, direct); 110} 111 112void qrio_set_opendrain_gpio(u8 port_off, u8 gpio_nr, u8 val) 113{ 114 u32 direct, mask; 115 116 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 117 118 mask = 1U << gpio_nr; 119 120 direct = in_be32(qrio_base + port_off + DIRECT_OFF); 121 if (val == 0) 122 /* set to output -> GPIO drives low */ 123 direct |= mask; 124 else 125 /* set to input -> GPIO floating */ 126 direct &= ~mask; 127 128 out_be32(qrio_base + port_off + DIRECT_OFF, direct); 129} 130 131#define WDMASK_OFF 0x16 132 133void qrio_wdmask(u8 bit, bool wden) 134{ 135 u16 wdmask; 136 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 137 138 wdmask = in_be16(qrio_base + WDMASK_OFF); 139 140 if (wden) 141 wdmask |= (1 << bit); 142 else 143 wdmask &= ~(1 << bit); 144 145 out_be16(qrio_base + WDMASK_OFF, wdmask); 146} 147 148#define PRST_OFF 0x1a 149 150void qrio_prst(u8 bit, bool en, bool wden) 151{ 152 u16 prst; 153 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 154 155 qrio_wdmask(bit, wden); 156 157 prst = in_be16(qrio_base + PRST_OFF); 158 159 if (en) 160 prst &= ~(1 << bit); 161 else 162 prst |= (1 << bit); 163 164 out_be16(qrio_base + PRST_OFF, prst); 165} 166 167#define PRSTCFG_OFF 0x1c 168 169void qrio_prstcfg(u8 bit, u8 mode) 170{ 171 unsigned long prstcfg; 172 u8 i; 173 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 174 175 prstcfg = in_be32(qrio_base + PRSTCFG_OFF); 176 177 for (i = 0; i < 2; i++) { 178 if (mode & (1 << i)) 179 __set_bit(2 * bit + i, &prstcfg); 180 else 181 __clear_bit(2 * bit + i, &prstcfg); 182 } 183 184 out_be32(qrio_base + PRSTCFG_OFF, prstcfg); 185} 186 187#define CTRLH_OFF 0x02 188#define CTRLH_WRL_BOOT 0x01 189#define CTRLH_WRL_UNITRUN 0x02 190 191void qrio_set_leds(void) 192{ 193 u8 ctrlh; 194 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 195 196 /* set UNIT LED to RED and BOOT LED to ON */ 197 ctrlh = in_8(qrio_base + CTRLH_OFF); 198 ctrlh |= (CTRLH_WRL_BOOT | CTRLH_WRL_UNITRUN); 199 out_8(qrio_base + CTRLH_OFF, ctrlh); 200} 201 202#define CTRLL_OFF 0x03 203#define CTRLL_WRB_BUFENA 0x20 204 205void qrio_enable_app_buffer(void) 206{ 207 u8 ctrll; 208 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 209 210 /* enable application buffer */ 211 ctrll = in_8(qrio_base + CTRLL_OFF); 212 ctrll |= (CTRLL_WRB_BUFENA); 213 out_8(qrio_base + CTRLL_OFF, ctrll); 214} 215 216#define REASON1_OFF 0x12 217#define REASON1_CPUWD 0x01 218 219void qrio_cpuwd_flag(bool flag) 220{ 221 u8 reason1; 222 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 223 224 reason1 = in_8(qrio_base + REASON1_OFF); 225 if (flag) 226 reason1 |= REASON1_CPUWD; 227 else 228 reason1 &= ~REASON1_CPUWD; 229 out_8(qrio_base + REASON1_OFF, reason1); 230} 231 232#define REASON0_OFF 0x13 233#define REASON0_SWURST 0x80 234#define REASON0_CPURST 0x40 235#define REASON0_BPRST 0x20 236#define REASON0_COPRST 0x10 237#define REASON0_SWCRST 0x08 238#define REASON0_WDRST 0x04 239#define REASON0_KBRST 0x02 240#define REASON0_POWUP 0x01 241#define UNIT_RESET\ 242 (REASON0_POWUP | REASON0_COPRST | REASON0_KBRST |\ 243 REASON0_BPRST | REASON0_SWURST | REASON0_WDRST) 244#define CORE_RESET ((REASON1_CPUWD << 8) | REASON0_SWCRST) 245 246bool qrio_reason_unitrst(void) 247{ 248 u16 reason; 249 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 250 251 reason = in_be16(qrio_base + REASON1_OFF); 252 253 return (reason & UNIT_RESET) > 0; 254} 255 256#define RSTCFG_OFF 0x11 257 258void qrio_uprstreq(u8 mode) 259{ 260 u32 rstcfg; 261 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 262 263 rstcfg = in_8(qrio_base + RSTCFG_OFF); 264 265 if (mode & UPREQ_CORE_RST) 266 rstcfg |= UPREQ_CORE_RST; 267 else 268 rstcfg &= ~UPREQ_CORE_RST; 269 270 out_8(qrio_base + RSTCFG_OFF, rstcfg); 271} 272 273/* Early bootcount memory area is avilable starting from QRIO3 Rev.2 */ 274#define QRIO3_ID 0x71 275#define QRIO3_REV 0x02 276#define EBOOTCNT_OFF 0x28 277 278ulong early_bootcount_load(void) 279{ 280 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 281 u16 id_rev = in_be16(qrio_base + ID_REV_OFF); 282 u8 id = (id_rev >> 8) & 0xff; 283 u8 rev = id_rev & 0xff; 284 u32 ebootcount = 0; 285 286 if (id == QRIO3_ID && rev >= QRIO3_REV) { 287 ebootcount = in_be32(qrio_base + EBOOTCNT_OFF); 288 } else { 289 printf("QRIO: warning: early bootcount not supported, "); 290 printf("id = %u, rev = %u\n", id, rev); 291 } 292 293 return ebootcount; 294} 295 296void early_bootcount_store(ulong ebootcount) 297{ 298 void __iomem *qrio_base = (void *)CFG_SYS_QRIO_BASE; 299 u16 id_rev = in_be16(qrio_base + ID_REV_OFF); 300 u8 id = (id_rev >> 8) & 0xff; 301 u8 rev = id_rev & 0xff; 302 303 if (id == QRIO3_ID && rev >= QRIO3_REV) { 304 out_be32(qrio_base + EBOOTCNT_OFF, ebootcount); 305 } else { 306 printf("QRIO: warning: early bootcount not supported, "); 307 printf("id = %u, rev = %u\n", id, rev); 308 } 309} 310 311/* I2C deblocking uses the algorithm defined in board/keymile/common/common.c 312 * 2 dedicated QRIO GPIOs externally pull the SCL and SDA lines 313 * For I2C only the low state is activly driven and high state is pulled-up 314 * by a resistor. Therefore the deblock GPIOs are used 315 * -> as an active output to drive a low state 316 * -> as an open-drain input to have a pulled-up high state 317 */ 318 319/* By default deblock GPIOs are floating */ 320void i2c_deblock_gpio_cfg(void) 321{ 322 /* set I2C bus 1 deblocking GPIOs input, but 0 value for open drain */ 323 qrio_gpio_direction_input(KM_I2C_DEBLOCK_PORT, 324 KM_I2C_DEBLOCK_SCL); 325 qrio_gpio_direction_input(KM_I2C_DEBLOCK_PORT, 326 KM_I2C_DEBLOCK_SDA); 327 328 qrio_set_gpio(KM_I2C_DEBLOCK_PORT, 329 KM_I2C_DEBLOCK_SCL, 0); 330 qrio_set_gpio(KM_I2C_DEBLOCK_PORT, 331 KM_I2C_DEBLOCK_SDA, 0); 332} 333 334void set_sda(int state) 335{ 336 qrio_set_opendrain_gpio(KM_I2C_DEBLOCK_PORT, 337 KM_I2C_DEBLOCK_SDA, state); 338} 339 340void set_scl(int state) 341{ 342 qrio_set_opendrain_gpio(KM_I2C_DEBLOCK_PORT, 343 KM_I2C_DEBLOCK_SCL, state); 344} 345 346int get_sda(void) 347{ 348 return qrio_get_gpio(KM_I2C_DEBLOCK_PORT, 349 KM_I2C_DEBLOCK_SDA); 350} 351 352int get_scl(void) 353{ 354 return qrio_get_gpio(KM_I2C_DEBLOCK_PORT, 355 KM_I2C_DEBLOCK_SCL); 356} 357