@@ -61,34 +61,80 @@ struct gpio_sifive_data {
6161#define DEV_GPIO_DATA (dev ) \
6262 ((struct gpio_sifive_data *)(dev)->driver_data)
6363
64+ /* _irq_level and _level2_irq are copied from
65+ * soc/riscv/riscv-privileged/common/soc_common_irq.c
66+ * Ideally this kind of thing should be made available in include/irq.h or
67+ * somewhere similar since the multi-level IRQ format is generic to
68+ Zephyr, and then both this copy and the one in riscv-privileged
69+ * be removed for the shared implementation
70+ */
71+ static inline unsigned int _irq_level (unsigned int irq )
72+ {
73+ return ((irq >> 8 ) && 0xff ) == 0U ? 1 : 2 ;
74+ }
75+
76+ static inline unsigned int _level2_irq (unsigned int irq )
77+ {
78+ return (irq >> 8 ) - 1 ;
79+ }
80+
81+ /* Given gpio_irq_base and the pin number, return the IRQ number for the pin */
82+ static inline unsigned int gpio_sifive_pin_irq (unsigned int base_irq , int pin )
83+ {
84+ unsigned int level = _irq_level (base_irq );
85+ unsigned int pin_irq = 0 ;
86+
87+ if (level == 1 ) {
88+ pin_irq = base_irq + pin ;
89+ } else if (level == 2 ) {
90+ pin_irq = base_irq + (pin << 8 );
91+ }
92+
93+ return pin_irq ;
94+ }
95+
96+ /* Given the PLIC source number, return the number of the GPIO pin associated
97+ * with the interrupt
98+ */
99+ static inline int gpio_sifive_plic_to_pin (unsigned int base_irq , int plic_irq )
100+ {
101+ unsigned int level = _irq_level (base_irq );
102+
103+ if (level == 2 ) {
104+ base_irq = _level2_irq (base_irq );
105+ }
106+
107+ return (plic_irq - base_irq );
108+ }
109+
64110static void gpio_sifive_irq_handler (void * arg )
65111{
66112 struct device * dev = (struct device * )arg ;
67113 struct gpio_sifive_data * data = DEV_GPIO_DATA (dev );
68114 volatile struct gpio_sifive_t * gpio = DEV_GPIO (dev );
69115 const struct gpio_sifive_config * cfg = DEV_GPIO_CFG (dev );
70- int pin_mask ;
116+ int pin ;
71117
72118 /* Get the pin number generating the interrupt */
73- pin_mask = 1 << (riscv_plic_get_irq () - cfg -> gpio_irq_base );
74-
75- /* Call the corresponding callback registered for the pin */
76- gpio_fire_callbacks (& data -> cb , dev , pin_mask );
119+ pin = gpio_sifive_plic_to_pin (cfg -> gpio_irq_base , riscv_plic_get_irq ());
77120
78121 /*
79122 * Write to either the rise_ip, fall_ip, high_ip or low_ip registers
80123 * to indicate to GPIO controller that interrupt for the corresponding
81124 * pin has been handled.
82125 */
83- if (gpio -> rise_ip & pin_mask ) {
84- gpio -> rise_ip = pin_mask ;
85- } else if (gpio -> fall_ip & pin_mask ) {
86- gpio -> fall_ip = pin_mask ;
87- } else if (gpio -> high_ip & pin_mask ) {
88- gpio -> high_ip = pin_mask ;
89- } else if (gpio -> low_ip & pin_mask ) {
90- gpio -> low_ip = pin_mask ;
126+ if (gpio -> rise_ip & BIT ( pin ) ) {
127+ gpio -> rise_ip = BIT ( pin ) ;
128+ } else if (gpio -> fall_ip & BIT ( pin ) ) {
129+ gpio -> fall_ip = BIT ( pin ) ;
130+ } else if (gpio -> high_ip & BIT ( pin ) ) {
131+ gpio -> high_ip = BIT ( pin ) ;
132+ } else if (gpio -> low_ip & BIT ( pin ) ) {
133+ gpio -> low_ip = BIT ( pin ) ;
91134 }
135+
136+ /* Call the corresponding callback registered for the pin */
137+ gpio_fire_callbacks (& data -> cb , dev , BIT (pin ));
92138}
93139
94140/**
@@ -116,94 +162,33 @@ static int gpio_sifive_config(struct device *dev,
116162 return - EINVAL ;
117163 }
118164
119- /* Configure gpio direction */
120- if (flags & GPIO_DIR_OUT ) {
121- gpio -> in_en &= ~BIT (pin );
122- gpio -> out_en |= BIT (pin );
123-
124- /*
125- * Account for polarity only for GPIO_DIR_OUT.
126- * invert register handles only output gpios
127- */
128- if (flags & GPIO_POL_INV ) {
129- gpio -> invert |= BIT (pin );
130- } else {
131- gpio -> invert &= ~BIT (pin );
132- }
133- } else {
134- gpio -> out_en &= ~BIT (pin );
135- gpio -> in_en |= BIT (pin );
136-
137- /* Polarity inversion is not supported for input gpio */
138- if (flags & GPIO_POL_INV ) {
139- return - EINVAL ;
140- }
141-
142- /*
143- * Pull-up can be configured only for input gpios.
144- * Only Pull-up can be enabled or disabled.
145- */
146- if ((flags & GPIO_PUD_MASK ) == GPIO_PUD_PULL_DOWN ) {
147- return - EINVAL ;
148- }
149-
150- if ((flags & GPIO_PUD_MASK ) == GPIO_PUD_PULL_UP ) {
151- gpio -> pue |= BIT (pin );
152- } else {
153- gpio -> pue &= ~BIT (pin );
154- }
165+ /* We cannot support open-source open-drain configuration */
166+ if ((flags & GPIO_SINGLE_ENDED ) != 0 ) {
167+ return - ENOTSUP ;
155168 }
156169
157- /*
158- * Configure interrupt if GPIO_INT is set.
159- * Here, we just configure the gpio interrupt behavior,
160- * we do not enable/disable interrupt for a particular
161- * gpio.
162- * Interrupt for a gpio is:
163- * 1) enabled only via a call to gpio_sifive_enable_callback.
164- * 2) disabled only via a call to gpio_sifive_disabled_callback.
165- */
166- if (!(flags & GPIO_INT )) {
167- return 0 ;
170+ /* We only support pull-ups, not pull-downs */
171+ if ((flags & GPIO_PULL_DOWN ) != 0 ) {
172+ return - ENOTSUP ;
168173 }
169174
170- /*
171- * Interrupt cannot be set for GPIO_DIR_OUT
175+ /* Set pull-up if requested */
176+ WRITE_BIT (gpio -> pue , pin , flags & GPIO_PULL_UP );
177+
178+ /* Set the initial output value before enabling output to avoid
179+ * glitches
172180 */
173- if (flags & GPIO_DIR_OUT ) {
174- return - EINVAL ;
181+ if (( flags & GPIO_OUTPUT_INIT_HIGH ) != 0 ) {
182+ gpio -> out_val |= BIT ( pin ) ;
175183 }
176-
177- /* Edge or Level triggered ? */
178- if (flags & GPIO_INT_EDGE ) {
179- gpio -> high_ie &= ~BIT (pin );
180- gpio -> low_ie &= ~BIT (pin );
181-
182- /* Rising Edge, Falling Edge or Double Edge ? */
183- if (flags & GPIO_INT_DOUBLE_EDGE ) {
184- gpio -> rise_ie |= BIT (pin );
185- gpio -> fall_ie |= BIT (pin );
186- } else if (flags & GPIO_INT_ACTIVE_HIGH ) {
187- gpio -> rise_ie |= BIT (pin );
188- gpio -> fall_ie &= ~BIT (pin );
189- } else {
190- gpio -> rise_ie &= ~BIT (pin );
191- gpio -> fall_ie |= BIT (pin );
192- }
193- } else {
194- gpio -> rise_ie &= ~BIT (pin );
195- gpio -> fall_ie &= ~BIT (pin );
196-
197- /* Level High ? */
198- if (flags & GPIO_INT_ACTIVE_HIGH ) {
199- gpio -> high_ie |= BIT (pin );
200- gpio -> low_ie &= ~BIT (pin );
201- } else {
202- gpio -> high_ie &= ~BIT (pin );
203- gpio -> low_ie |= BIT (pin );
204- }
184+ if ((flags & GPIO_OUTPUT_INIT_LOW ) != 0 ) {
185+ gpio -> out_val &= ~BIT (pin );
205186 }
206187
188+ /* Enable input/output */
189+ WRITE_BIT (gpio -> out_en , pin , flags & GPIO_OUTPUT );
190+ WRITE_BIT (gpio -> in_en , pin , flags & GPIO_INPUT );
191+
207192 return 0 ;
208193}
209194
@@ -284,6 +269,117 @@ static int gpio_sifive_read(struct device *dev,
284269 return 0 ;
285270}
286271
272+ static int gpio_sifive_port_get_raw (struct device * dev ,
273+ gpio_port_value_t * value )
274+ {
275+ volatile struct gpio_sifive_t * gpio = DEV_GPIO (dev );
276+
277+ * value = gpio -> in_val ;
278+
279+ return 0 ;
280+ }
281+
282+ static int gpio_sifive_port_set_masked_raw (struct device * dev ,
283+ gpio_port_pins_t mask ,
284+ gpio_port_value_t value )
285+ {
286+ volatile struct gpio_sifive_t * gpio = DEV_GPIO (dev );
287+
288+ gpio -> out_val = (gpio -> out_val & ~mask ) | (value & mask );
289+
290+ return 0 ;
291+ }
292+
293+ static int gpio_sifive_port_set_bits_raw (struct device * dev ,
294+ gpio_port_pins_t mask )
295+ {
296+ volatile struct gpio_sifive_t * gpio = DEV_GPIO (dev );
297+
298+ gpio -> out_val |= mask ;
299+
300+ return 0 ;
301+ }
302+
303+ static int gpio_sifive_port_clear_bits_raw (struct device * dev ,
304+ gpio_port_pins_t mask )
305+ {
306+ volatile struct gpio_sifive_t * gpio = DEV_GPIO (dev );
307+
308+ gpio -> out_val &= ~mask ;
309+
310+ return 0 ;
311+ }
312+
313+ static int gpio_sifive_port_toggle_bits (struct device * dev ,
314+ gpio_port_pins_t mask )
315+ {
316+ volatile struct gpio_sifive_t * gpio = DEV_GPIO (dev );
317+
318+ gpio -> out_val ^= mask ;
319+
320+ return 0 ;
321+ }
322+
323+ static int gpio_sifive_pin_interrupt_configure (struct device * dev ,
324+ unsigned int pin ,
325+ enum gpio_int_mode mode ,
326+ enum gpio_int_trig trig )
327+ {
328+ volatile struct gpio_sifive_t * gpio = DEV_GPIO (dev );
329+ const struct gpio_sifive_config * cfg = DEV_GPIO_CFG (dev );
330+
331+ switch (mode ) {
332+ case GPIO_INT_MODE_DISABLED :
333+ gpio -> rise_ie &= ~BIT (pin );
334+ gpio -> fall_ie &= ~BIT (pin );
335+ gpio -> high_ie &= ~BIT (pin );
336+ gpio -> low_ie &= ~BIT (pin );
337+ irq_disable (gpio_sifive_pin_irq (cfg -> gpio_irq_base , pin ));
338+ break ;
339+ case GPIO_INT_MODE_LEVEL :
340+ gpio -> rise_ie &= ~BIT (pin );
341+ gpio -> fall_ie &= ~BIT (pin );
342+
343+ if (trig == GPIO_INT_TRIG_HIGH ) {
344+ gpio -> high_ip = BIT (pin );
345+ gpio -> high_ie |= BIT (pin );
346+ gpio -> low_ie &= ~BIT (pin );
347+ } else if (trig == GPIO_INT_TRIG_LOW ) {
348+ gpio -> high_ie &= ~BIT (pin );
349+ gpio -> low_ip = BIT (pin );
350+ gpio -> low_ie |= BIT (pin );
351+ }
352+ irq_enable (gpio_sifive_pin_irq (cfg -> gpio_irq_base , pin ));
353+ break ;
354+ case GPIO_INT_MODE_EDGE :
355+ gpio -> high_ie &= ~BIT (pin );
356+ gpio -> low_ie &= ~BIT (pin );
357+
358+ /* Rising Edge, Falling Edge or Double Edge ? */
359+ if (trig == GPIO_INT_TRIG_HIGH ) {
360+ gpio -> rise_ip = BIT (pin );
361+ gpio -> rise_ie |= BIT (pin );
362+ gpio -> fall_ie &= ~BIT (pin );
363+ } else if (trig == GPIO_INT_TRIG_LOW ) {
364+ gpio -> rise_ie &= ~BIT (pin );
365+ gpio -> fall_ip = BIT (pin );
366+ gpio -> fall_ie |= BIT (pin );
367+ } else {
368+ gpio -> rise_ip = BIT (pin );
369+ gpio -> rise_ie |= BIT (pin );
370+ gpio -> fall_ip = BIT (pin );
371+ gpio -> fall_ie |= BIT (pin );
372+ }
373+ irq_enable (gpio_sifive_pin_irq (cfg -> gpio_irq_base , pin ));
374+ break ;
375+ default :
376+ __ASSERT (false, "Invalid MODE %d passed to driver" , mode );
377+ return - ENOTSUP ;
378+ }
379+
380+ return 0 ;
381+ }
382+
287383static int gpio_sifive_manage_callback (struct device * dev ,
288384 struct gpio_callback * callback ,
289385 bool set )
@@ -308,7 +404,7 @@ static int gpio_sifive_enable_callback(struct device *dev,
308404 }
309405
310406 /* Enable interrupt for the pin at PLIC level */
311- irq_enable (cfg -> gpio_irq_base + pin );
407+ irq_enable (gpio_sifive_pin_irq ( cfg -> gpio_irq_base , pin ) );
312408
313409 return 0 ;
314410}
@@ -328,18 +424,24 @@ static int gpio_sifive_disable_callback(struct device *dev,
328424 }
329425
330426 /* Disable interrupt for the pin at PLIC level */
331- irq_disable (cfg -> gpio_irq_base + pin );
427+ irq_disable (gpio_sifive_pin_irq ( cfg -> gpio_irq_base , pin ) );
332428
333429 return 0 ;
334430}
335431
336432static const struct gpio_driver_api gpio_sifive_driver = {
337- .config = gpio_sifive_config ,
338- .write = gpio_sifive_write ,
339- .read = gpio_sifive_read ,
340- .manage_callback = gpio_sifive_manage_callback ,
341- .enable_callback = gpio_sifive_enable_callback ,
342- .disable_callback = gpio_sifive_disable_callback ,
433+ .config = gpio_sifive_config ,
434+ .write = gpio_sifive_write ,
435+ .read = gpio_sifive_read ,
436+ .port_get_raw = gpio_sifive_port_get_raw ,
437+ .port_set_masked_raw = gpio_sifive_port_set_masked_raw ,
438+ .port_set_bits_raw = gpio_sifive_port_set_bits_raw ,
439+ .port_clear_bits_raw = gpio_sifive_port_clear_bits_raw ,
440+ .port_toggle_bits = gpio_sifive_port_toggle_bits ,
441+ .pin_interrupt_configure = gpio_sifive_pin_interrupt_configure ,
442+ .manage_callback = gpio_sifive_manage_callback ,
443+ .enable_callback = gpio_sifive_enable_callback ,
444+ .disable_callback = gpio_sifive_disable_callback ,
343445};
344446
345447/**
@@ -375,9 +477,9 @@ static int gpio_sifive_init(struct device *dev)
375477static void gpio_sifive_cfg_0 (void );
376478
377479static const struct gpio_sifive_config gpio_sifive_config0 = {
378- .gpio_base_addr = DT_INST_0_SIFIVE_GPIO0_BASE_ADDRESS ,
379- .gpio_irq_base = DT_INST_0_SIFIVE_GPIO0_IRQ_0 ,
380- .gpio_cfg_func = gpio_sifive_cfg_0 ,
480+ .gpio_base_addr = DT_INST_0_SIFIVE_GPIO0_BASE_ADDRESS ,
481+ .gpio_irq_base = DT_INST_0_SIFIVE_GPIO0_IRQ_0 ,
482+ .gpio_cfg_func = gpio_sifive_cfg_0 ,
381483};
382484
383485static struct gpio_sifive_data gpio_sifive_data0 ;
0 commit comments