Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*.lo
*.la
*.in
confdefs.h

# generated source files
src/jtag/minidriver_imp.h
Expand Down
106 changes: 74 additions & 32 deletions src/jtag/drivers/bcm2835gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ static off_t bcm2835_peri_base = 0x20000000;
*(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
#define OUT_GPIO(g) SET_MODE_GPIO(g, BCM2835_GPIO_MODE_OUTPUT)

#define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */
#define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
#define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
#define GPIO_SET(g) (*(pio_base+7+((g&32)>>5))) /* sets bits which are 1, ignores bits which are 0 */
#define GPIO_CLR(g) (*(pio_base+10+((g&32)>>5))) /* clears bits which are 1, ignores bits which are 0 */
#define GPIO_LEV(g) (*(pio_base+13+((g&32)>>5))) /* current level of the pin */

static int dev_mem_fd;
static volatile uint32_t *pio_base = MAP_FAILED;
Expand Down Expand Up @@ -83,8 +83,11 @@ static inline void bcm2835_delay(void)

static bool is_gpio_config_valid(enum adapter_gpio_config_index idx)
{
/* Only chip 0 is supported, accept unset value (-1) too */
return adapter_gpio_config[idx].gpio_num <= 31;
/* Only chip 0 is supported, accept unset value (-1) too, allow
* any gpio up to including 45 */
return (adapter_gpio_config[idx].chip_num == 0 ||
adapter_gpio_config[idx].chip_num == ADAPTER_GPIO_NOT_SET)
&& adapter_gpio_config[idx].gpio_num <= 45;
}

static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value)
Expand All @@ -93,9 +96,9 @@ static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int va
switch (gpio_config->drive) {
case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL:
if (value)
GPIO_SET = 1 << gpio_config->gpio_num;
GPIO_SET(gpio_config->gpio_num) = 1 << (gpio_config->gpio_num & 0x1f);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO it looks a bit weird seeing gpio_config->gpio_num repeated on both sides of the = sign? But perhaps "fixing" that would be too much of a departure from the way the existing code was working? 🤷

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree - could rewrite entirely if you'd like and make set an entire macro?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really my call to make. What does @P33M think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@P33M any thoughts?

else
GPIO_CLR = 1 << gpio_config->gpio_num;
GPIO_CLR(gpio_config->gpio_num) = 1 << (gpio_config->gpio_num & 0x1f);
/* For performance reasons assume the GPIO is already set as an output
* and therefore the call can be omitted here.
*/
Expand All @@ -104,13 +107,13 @@ static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int va
if (value) {
INP_GPIO(gpio_config->gpio_num);
} else {
GPIO_CLR = 1 << gpio_config->gpio_num;
GPIO_CLR(gpio_config->gpio_num) = 1 << (gpio_config->gpio_num & 0x1f);
OUT_GPIO(gpio_config->gpio_num);
}
break;
case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE:
if (value) {
GPIO_SET = 1 << gpio_config->gpio_num;
GPIO_SET(gpio_config->gpio_num) = 1 << (gpio_config->gpio_num & 0x1f);
OUT_GPIO(gpio_config->gpio_num);
} else {
INP_GPIO(gpio_config->gpio_num);
Expand All @@ -126,9 +129,9 @@ static void restore_gpio(enum adapter_gpio_config_index idx)
SET_MODE_GPIO(adapter_gpio_config[idx].gpio_num, initial_gpio_state[idx].mode);
if (initial_gpio_state[idx].mode == BCM2835_GPIO_MODE_OUTPUT) {
if (initial_gpio_state[idx].output_level)
GPIO_SET = 1 << adapter_gpio_config[idx].gpio_num;
GPIO_SET(adapter_gpio_config[idx].gpio_num) = 1 << (adapter_gpio_config[idx].gpio_num & 0x1f);
else
GPIO_CLR = 1 << adapter_gpio_config[idx].gpio_num;
GPIO_CLR(adapter_gpio_config[idx].gpio_num) = 1 << (adapter_gpio_config[idx].gpio_num & 0x1f);
}
}
bcm2835_gpio_synchronize();
Expand All @@ -140,8 +143,8 @@ static void initialize_gpio(enum adapter_gpio_config_index idx)
return;

initial_gpio_state[idx].mode = MODE_GPIO(adapter_gpio_config[idx].gpio_num);
unsigned int shift = adapter_gpio_config[idx].gpio_num;
initial_gpio_state[idx].output_level = (GPIO_LEV >> shift) & 1;
unsigned int shift = adapter_gpio_config[idx].gpio_num & 0x1f;
initial_gpio_state[idx].output_level = (GPIO_LEV(adapter_gpio_config[idx].gpio_num) >> shift) & 1;
LOG_DEBUG("saved GPIO mode for %s (GPIO %d %d): %d",
adapter_gpio_get_name(idx), adapter_gpio_config[idx].chip_num, adapter_gpio_config[idx].gpio_num,
initial_gpio_state[idx].mode);
Expand Down Expand Up @@ -172,23 +175,46 @@ static void initialize_gpio(enum adapter_gpio_config_index idx)

static bb_value_t bcm2835gpio_read(void)
{
unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].gpio_num;
uint32_t value = (GPIO_LEV >> shift) & 1;
unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].gpio_num & 0x1f;
uint32_t value = (GPIO_LEV(adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].gpio_num) >> shift) & 1;
return value ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].active_low ? BB_HIGH : BB_LOW);

}

static int bcm2835gpio_write(int tck, int tms, int tdi)
{
uint32_t set = tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num |
tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num |
tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;
uint32_t clear = !tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num |
!tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num |
!tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;

GPIO_SET = set;
GPIO_CLR = clear;
if ((adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num >= 32) ==
(adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num >= 32) &&
(adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num >= 32) ==
(adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num >= 32)) {
uint32_t set = tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num |
tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num |
tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;
uint32_t clear = !tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num |
!tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num |
!tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;

GPIO_SET(adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num) = set;
GPIO_CLR(adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num) = clear;
} else {
uint32_t set = tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num;
uint32_t clear = !tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num;

GPIO_SET(adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num) = set;
GPIO_CLR(adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num) = clear;

set = tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num;
clear = !tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num;

GPIO_SET(adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num) = set;
GPIO_CLR(adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num) = clear;

set = tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;
clear = !tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;

GPIO_SET(adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num) = set;
GPIO_CLR(adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num) = clear;
}
bcm2835_gpio_synchronize();

bcm2835_delay();
Expand All @@ -202,13 +228,29 @@ static int bcm2835gpio_swd_write_fast(int swclk, int swdio)
swclk = swclk ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].active_low ? 1 : 0);
swdio = swdio ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].active_low ? 1 : 0);

uint32_t set = swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num |
swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
uint32_t clear = !swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num |
!swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
if ((adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num & 32) ==
(adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num & 32)) {

GPIO_SET = set;
GPIO_CLR = clear;
uint32_t set = swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num |
swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
uint32_t clear = !swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num |
!swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;

GPIO_SET(adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num) = set;
GPIO_CLR(adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num) = clear;
} else {
uint32_t set = swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num;
uint32_t clear = !swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num;

GPIO_SET(adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num) = set;
GPIO_CLR(adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num) = clear;

set = swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
clear = !swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;

GPIO_SET(adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num) = set;
GPIO_CLR(adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num) = clear;
}
bcm2835_gpio_synchronize();

bcm2835_delay();
Expand Down Expand Up @@ -266,8 +308,8 @@ static void bcm2835_swdio_drive(bool is_output)

static int bcm2835_swdio_read(void)
{
unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
uint32_t value = (GPIO_LEV >> shift) & 1;
unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num & 0x1f;
uint32_t value = (GPIO_LEV(adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num) >> shift) & 1;
return value ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].active_low ? 1 : 0);
}

Expand Down