stm32: Unify enable_pclock() code

Unify the handling of the enable_pclock() and is_enabled_pclock() code
across all stm32 chips.  All chips will now perform a peripheral reset
on enable_pclock() (this is a change for stm32f0 and stm32h7).  The
enable_pclock() code will now also disable irqs during the enable.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2021-12-24 12:23:56 -05:00
parent 9bdd61758e
commit 8b6753d68f
8 changed files with 129 additions and 242 deletions

View file

@ -19,71 +19,29 @@
#define FREQ_PERIPH 64000000
#define FREQ_USB 48000000
// Map an APB peripheral address to an enable bit
static int
lookup_apb_bit(uint32_t periph_base)
// Map a peripheral address to its enable bits
struct cline
lookup_clock_line(uint32_t periph_base)
{
if (periph_base >= IOPORT_BASE) {
uint32_t bit = 1 << ((periph_base - IOPORT_BASE) / 0x400);
return (struct cline){.en=&RCC->IOPENR, .rst=&RCC->IOPRSTR, .bit=bit};
} else if (periph_base >= AHBPERIPH_BASE) {
uint32_t bit = 1 << ((periph_base - AHBPERIPH_BASE) / 0x400);
return (struct cline){.en=&RCC->AHBENR, .rst=&RCC->AHBRSTR, .bit=bit};
}
if (periph_base == USB_BASE)
return 13;
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<13};
if (periph_base == CRS_BASE)
return 16;
return (struct cline){.en=&RCC->APBENR1,.rst=&RCC->APBRSTR1,.bit=1<<16};
if (periph_base == SPI1_BASE)
return 32 + 12;
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<12};
if (periph_base == USART1_BASE)
return 32 + 14;
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<14};
if (periph_base == ADC1_BASE)
return 32 + 20;
return (periph_base - APBPERIPH_BASE) / 0x400;
}
// Enable a peripheral clock
void
enable_pclock(uint32_t periph_base)
{
if (periph_base >= IOPORT_BASE) {
uint32_t pos = (periph_base - IOPORT_BASE) / 0x400;
RCC->IOPENR |= 1 << pos;
RCC->IOPENR;
RCC->IOPRSTR |= (1<<pos);
RCC->IOPRSTR &= ~(1<<pos);
} else if (periph_base >= AHBPERIPH_BASE) {
uint32_t pos = (periph_base - AHBPERIPH_BASE) / 0x400;
RCC->AHBENR |= 1 << pos;
RCC->AHBENR;
RCC->AHBRSTR |= (1<<pos);
RCC->AHBRSTR &= ~(1<<pos);
} else {
uint32_t pos = lookup_apb_bit(periph_base);
if (pos < 32) {
RCC->APBENR1 |= 1 << pos;
RCC->APBENR1;
RCC->APBRSTR1 |= (1 << pos);
RCC->APBRSTR1 &= ~(1 << pos);
} else {
RCC->APBENR2 |= 1 << (pos - 32);
RCC->APBENR2;
RCC->APBRSTR2 |= (1 << (pos - 32));
RCC->APBRSTR2 &= ~(1 << (pos - 32));
}
}
}
// Check if a peripheral clock has been enabled
int
is_enabled_pclock(uint32_t periph_base)
{
if (periph_base >= IOPORT_BASE) {
uint32_t pos = (periph_base - IOPORT_BASE) / 0x400;
return RCC->IOPENR & (1 << pos);
} else if (periph_base >= AHBPERIPH_BASE) {
uint32_t pos = (periph_base - AHBPERIPH_BASE) / 0x400;
return RCC->AHBENR & (1 << pos);
} else {
uint32_t pos = lookup_apb_bit(periph_base);
if (pos < 32)
return RCC->APBENR1 & (1 << pos);
return RCC->APBENR2 & (1 << (pos - 32));
}
return (struct cline){.en=&RCC->APBENR2,.rst=&RCC->APBRSTR2,.bit=1<<20};
uint32_t bit = 1 << ((periph_base - APBPERIPH_BASE) / 0x400);
return (struct cline){.en=&RCC->APBENR1, .rst=&RCC->APBRSTR1, .bit=bit};
}
// Return the frequency of the given peripheral clock