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 static 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