1 /*
2  * Copyright (c) 2021 IoT.bzh
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  */
7 
8 #define DT_DRV_COMPAT renesas_rcar_pfc
9 
10 #include <zephyr/arch/cpu.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/drivers/pinctrl.h>
13 #include <zephyr/init.h>
14 #include <zephyr/sys/util.h>
15 #include <zephyr/sys/device_mmio.h>
16 
17 DEVICE_MMIO_TOPLEVEL_STATIC(pfc, DT_DRV_INST(0));
18 
19 #define PFC_REG_BASE  DEVICE_MMIO_TOPLEVEL_GET(pfc)
20 #define PFC_RCAR_PMMR 0x0
21 #define PFC_RCAR_GPSR 0x100
22 #define PFC_RCAR_IPSR 0x200
23 
24 /*
25  * Each drive step is either encoded in 2 or 3 bits.
26  * So based on a 24 mA maximum value each step is either
27  * 24/4 mA or 24/8 mA.
28  */
29 #define PFC_RCAR_DRIVE_MAX 24U
30 #define PFC_RCAR_DRIVE_STEP(size) \
31 	(size == 2 ? PFC_RCAR_DRIVE_MAX / 4 : PFC_RCAR_DRIVE_MAX / 8)
32 
33 /* Some registers such as IPSR GPSR or DRVCTRL are protected and
34  * must be preceded to a write to PMMR with the inverse value.
35  */
pfc_rcar_write(uint32_t offs,uint32_t val)36 static void pfc_rcar_write(uint32_t offs, uint32_t val)
37 {
38 	sys_write32(~val, PFC_REG_BASE + PFC_RCAR_PMMR);
39 	sys_write32(val, PFC_REG_BASE + offs);
40 }
41 
42 /* Set the pin either in gpio or peripheral */
pfc_rcar_set_gpsr(uint16_t pin,bool peripheral)43 static void pfc_rcar_set_gpsr(uint16_t pin, bool peripheral)
44 {
45 	uint8_t bank = pin / 32;
46 	uint8_t bit = pin % 32;
47 	uint32_t val = sys_read32(PFC_REG_BASE + PFC_RCAR_GPSR +
48 				  bank * sizeof(uint32_t));
49 
50 	if (peripheral) {
51 		val |= BIT(bit);
52 	} else {
53 		val &= ~BIT(bit);
54 	}
55 	pfc_rcar_write(PFC_RCAR_GPSR + bank * sizeof(uint32_t), val);
56 }
57 
58 /* Set peripheral function */
pfc_rcar_set_ipsr(const struct rcar_pin_func * rcar_func)59 static void pfc_rcar_set_ipsr(const struct rcar_pin_func *rcar_func)
60 {
61 	uint16_t reg_offs = PFC_RCAR_IPSR + rcar_func->bank * sizeof(uint32_t);
62 	uint32_t val = sys_read32(PFC_REG_BASE + reg_offs);
63 
64 	val &= ~(0xFU << rcar_func->shift);
65 	val |= (rcar_func->func << rcar_func->shift);
66 	pfc_rcar_write(reg_offs, val);
67 }
68 
pfc_rcar_get_drive_reg(uint16_t pin,uint8_t * offset,uint8_t * size)69 static uint32_t pfc_rcar_get_drive_reg(uint16_t pin, uint8_t *offset,
70 				       uint8_t *size)
71 {
72 	const struct pfc_drive_reg *drive_regs = pfc_rcar_get_drive_regs();
73 
74 	while (drive_regs->reg != 0U) {
75 		for (size_t i = 0U; i < ARRAY_SIZE(drive_regs->fields); i++) {
76 			if (drive_regs->fields[i].pin == pin) {
77 				*offset = drive_regs->fields[i].offset;
78 				*size = drive_regs->fields[i].size;
79 				return drive_regs->reg;
80 			}
81 		}
82 		drive_regs++;
83 	}
84 
85 	return 0;
86 }
87 
88 /*
89  * Maximum drive strength is 24mA. This value can be lowered
90  * using DRVCTRLx registers, some pins have 8 steps (3 bits size encoded)
91  * some have 4 steps (2 bits size encoded).
92  */
pfc_rcar_set_drive_strength(uint16_t pin,uint8_t strength)93 static int pfc_rcar_set_drive_strength(uint16_t pin, uint8_t strength)
94 {
95 	uint8_t offset, size, step;
96 	uint32_t reg, val;
97 
98 	reg = pfc_rcar_get_drive_reg(pin, &offset, &size);
99 	if (reg == 0U) {
100 		return -EINVAL;
101 	}
102 
103 	step = PFC_RCAR_DRIVE_STEP(size);
104 	if ((strength < step) || (strength > PFC_RCAR_DRIVE_MAX)) {
105 		return -EINVAL;
106 	}
107 
108 	/* Convert the value from mA based on a full drive strength
109 	 * value of 24mA.
110 	 */
111 	strength = (strength / step) - 1U;
112 	/* clear previous drive strength value */
113 	val = sys_read32(PFC_REG_BASE + reg);
114 	val &= ~GENMASK(offset + size - 1U, offset);
115 	val |= strength << offset;
116 
117 	pfc_rcar_write(reg, val);
118 
119 	return 0;
120 }
121 
pfc_rcar_get_bias_reg(uint16_t pin,uint8_t * bit)122 static const struct pfc_bias_reg *pfc_rcar_get_bias_reg(uint16_t pin,
123 							uint8_t *bit)
124 {
125 	const struct pfc_bias_reg *bias_regs = pfc_rcar_get_bias_regs();
126 
127 	/* Loop around all the registers to find the bit for a given pin */
128 	while (bias_regs->puen && bias_regs->pud) {
129 		for (size_t i = 0U; i < ARRAY_SIZE(bias_regs->pins); i++) {
130 			if (bias_regs->pins[i] == pin) {
131 				*bit = i;
132 				return bias_regs;
133 			}
134 		}
135 		bias_regs++;
136 	}
137 
138 	return NULL;
139 }
140 
pfc_rcar_set_bias(uint16_t pin,uint16_t flags)141 int pfc_rcar_set_bias(uint16_t pin, uint16_t flags)
142 {
143 	uint32_t val;
144 	uint8_t bit;
145 	const struct pfc_bias_reg *bias_reg = pfc_rcar_get_bias_reg(pin, &bit);
146 
147 	if (bias_reg == NULL) {
148 		return -EINVAL;
149 	}
150 
151 	/* pull enable/disable*/
152 	val = sys_read32(PFC_REG_BASE + bias_reg->puen);
153 	if ((flags & RCAR_PIN_FLAGS_PUEN) == 0U) {
154 		sys_write32(val & ~BIT(bit), PFC_REG_BASE + bias_reg->puen);
155 		return 0;
156 	}
157 	sys_write32(val | BIT(bit), PFC_REG_BASE + bias_reg->puen);
158 
159 	/* pull - up/down */
160 	val = sys_read32(PFC_REG_BASE + bias_reg->pud);
161 	if (flags & RCAR_PIN_FLAGS_PUD) {
162 		sys_write32(val | BIT(bit), PFC_REG_BASE + bias_reg->pud);
163 	} else {
164 		sys_write32(val & ~BIT(bit), PFC_REG_BASE + bias_reg->pud);
165 	}
166 	return 0;
167 }
168 
pinctrl_configure_pin(const pinctrl_soc_pin_t * pin)169 int pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
170 {
171 	int ret = 0;
172 
173 	/* Set pin as GPIO if capable */
174 	if (RCAR_IS_GP_PIN(pin->pin)) {
175 		pfc_rcar_set_gpsr(pin->pin, false);
176 	} else if ((pin->flags & RCAR_PIN_FLAGS_FUNC_SET) == 0U) {
177 		/* A function must be set for non GPIO capable pin */
178 		return -EINVAL;
179 	}
180 
181 	/* Select function for pin */
182 	if ((pin->flags & RCAR_PIN_FLAGS_FUNC_SET) != 0U) {
183 		pfc_rcar_set_ipsr(&pin->func);
184 
185 		if (RCAR_IS_GP_PIN(pin->pin)) {
186 			pfc_rcar_set_gpsr(pin->pin, true);
187 		}
188 
189 		if ((pin->flags & RCAR_PIN_FLAGS_PULL_SET) != 0U) {
190 			ret = pfc_rcar_set_bias(pin->pin, pin->flags);
191 			if (ret < 0) {
192 				return ret;
193 			}
194 		}
195 	}
196 
197 	if (pin->drive_strength != 0U) {
198 		ret = pfc_rcar_set_drive_strength(pin->pin,
199 						  pin->drive_strength);
200 	}
201 
202 	return ret;
203 }
204 
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)205 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
206 			   uintptr_t reg)
207 {
208 	int ret = 0;
209 
210 	ARG_UNUSED(reg);
211 	while (pin_cnt-- > 0U) {
212 		ret = pinctrl_configure_pin(pins++);
213 		if (ret < 0) {
214 			break;
215 		}
216 	}
217 
218 	return ret;
219 }
220 
pfc_rcar_driver_init(void)221 __boot_func static int pfc_rcar_driver_init(void)
222 {
223 	DEVICE_MMIO_TOPLEVEL_MAP(pfc, K_MEM_CACHE_NONE);
224 	return 0;
225 }
226 
227 SYS_INIT(pfc_rcar_driver_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
228