Skip to content
This repository has been archived by the owner on Jul 3, 2024. It is now read-only.

Commit

Permalink
Merge pull request #442 from sifive/add-sifive-pwm
Browse files Browse the repository at this point in the history
Add support for Sifive-PWM.
  • Loading branch information
bsousi5 authored Mar 19, 2020
2 parents 3c8a23a + 30168f5 commit 59bf2c7
Show file tree
Hide file tree
Showing 33 changed files with 1,927 additions and 41 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@
[submodule "software/example-i2c"]
path = software/example-i2c
url = https://github.com/sifive/example-i2c.git
[submodule "software/example-pwm"]
path = software/example-pwm
url = https://github.com/sifive/example-pwm.git
[submodule "software/mem-latency"]
path = software/mem-latency
url = https://github.com/sifive/benchmark-mem-latency.git
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ operating systems to RISC-V.
atomic instruction set.
- example-i2c
- Demonstrates usage of the I2C API to communicate with I2C slaves.
- example-pwm
- Demonstrates usage of the PWM API to generate waveforms.
- mem-latency
- A memory test that measure the latency at different cache layers and memory blocks
- example-freertos-minimal
Expand Down
8 changes: 6 additions & 2 deletions bsp/freedom-e310-arty/core.dts
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,16 @@
reg = <0x8000000 0x4000>;
reg-names = "mem";
};
pwm@10015000 {
pwm0: pwm@10015000 {
compatible = "sifive,pwm0";
sifive,comparator-widthbits = <8>;
sifive,ncomparators = <4>;
interrupt-parent = <&plic>;
interrupts = <23 24 25 26>;
reg = <0x10015000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0F 0x0F>;
};
gpio0: gpio@10012000 {
compatible = "sifive,gpio0";
Expand All @@ -112,7 +116,7 @@
reg = <0x10013000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x30000 0x30000>;
pinmux = <&gpio0 0x0 0x30000>;
};
spi0: spi@10014000 {
compatible = "sifive,spi0";
Expand Down
19 changes: 19 additions & 0 deletions bsp/freedom-e310-arty/metal-inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ extern __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_g
/* --------------------- sifive_i2c0 ------------ */


/* --------------------- sifive_pwm0 ------------ */
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm);
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm);
extern __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx);
extern __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm);
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm);
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm);
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm);


/* --------------------- sifive_rtc0 ------------ */


Expand Down Expand Up @@ -199,6 +213,11 @@ struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = {
.gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio,
};

/* From pwm@10015000 */
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000 = {
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
};

/* From spi@10014000 */
struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = {
.spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
Expand Down
135 changes: 134 additions & 1 deletion bsp/freedom-e310-arty/metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@

#define METAL_MAX_I2C0_INTERRUPTS 0

#define __METAL_PWM_10015000_INTERRUPTS 4

#define METAL_MAX_PWM0_INTERRUPTS 4

#define METAL_MAX_PWM0_NCMP 4

#define __METAL_SERIAL_10013000_INTERRUPTS 1

#define METAL_MAX_UART_INTERRUPTS 1
Expand All @@ -80,6 +86,7 @@
#include <metal/pmp.h>
#include <metal/drivers/sifive_local-external-interrupts0.h>
#include <metal/drivers/sifive_gpio0.h>
#include <metal/drivers/sifive_pwm0.h>
#include <metal/drivers/sifive_spi0.h>
#include <metal/drivers/sifive_uart0.h>

Expand Down Expand Up @@ -109,6 +116,9 @@ struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_externa
/* From gpio@10012000 */
struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000;

/* From pwm@10015000 */
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000;

/* From spi@10014000 */
struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000;

Expand Down Expand Up @@ -505,6 +515,123 @@ static __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_g
/* --------------------- sifive_i2c0 ------------ */


/* --------------------- sifive_pwm0 ------------ */
static __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS;
}
else {
return 0;
}
}

static __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return METAL_SIFIVE_PWM0_10015000_SIZE;
}
else {
return 0;
}
}

static __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return (struct metal_clock *)&__metal_dt_clock_0.clock;
}
else {
return NULL;
}
}

static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
}
else {
return NULL;
}
}

static __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return 15;
}
else {
return 0;
}
}

static __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return 15;
}
else {
return 0;
}
}

static __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return __METAL_PWM_10015000_INTERRUPTS;
}
else {
return 0;
}
}

static __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm)
{
return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller;
}

static __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx)
{
if (((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 0)) {
return 23;
}
else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 1))) {
return 24;
}
else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 2))) {
return 25;
}
else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 3))) {
return 26;
}
else {
return 0;
}
}

static __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return 8;
}
else {
return 0;
}
}

static __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm)
{
if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) {
return 4;
}
else {
return 0;
}
}



/* --------------------- sifive_rtc0 ------------ */

static __inline__ unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi)
Expand Down Expand Up @@ -648,7 +775,7 @@ static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uar
static __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart)
{
if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) {
return 196608;
return 0;
}
else {
return 0;
Expand Down Expand Up @@ -752,6 +879,12 @@ struct __metal_driver_sifive_gpio_switch *__metal_switch_table[] = {
__asm__ (".weak __metal_i2c_table");
struct __metal_driver_sifive_i2c0 *__metal_i2c_table[] = {
NULL };
#define __METAL_DT_MAX_PWMS 1

__asm__ (".weak __metal_pwm_table");
struct __metal_driver_sifive_pwm0 *__metal_pwm_table[] = {
&__metal_dt_pwm_10015000};

#define __METAL_DT_MAX_RTCS 0

__asm__ (".weak __metal_rtc_table");
Expand Down
10 changes: 7 additions & 3 deletions bsp/qemu-sifive-e31/core.dts
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,16 @@
reg-names = "mem";
};

pwm@10015000 {
pwm0: pwm@10015000 {
compatible = "sifive,pwm0";
sifive,comparator-widthbits = <8>;
sifive,ncomparators = <4>;
interrupt-parent = <&plic>;
interrupts = <23 24 25 26>;
reg = <0x10015000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0F 0x0F>;
};
gpio0: gpio@10012000 {
compatible = "sifive,gpio0";
Expand All @@ -161,7 +165,7 @@
reg = <0x10013000 0x1000>;
reg-names = "control";
clocks = <&hfclk>;
pinmux = <&gpio0 0x30000 0x30000>;
pinmux = <&gpio0 0x0 0x30000>;
};
spi0: spi@10014000 {
compatible = "sifive,spi0";
Expand All @@ -170,7 +174,7 @@
reg = <0x10014000 0x1000 0x20000000 0x20000000>;
reg-names = "control", "mem";
clocks = <&hfclk>;
pinmux = <&gpio0 0x0003C 0x0003C>;
pinmux = <&gpio0 0x0 0x0003C>;
#address-cells = <1>;
#size-cells = <1>;
flash@0 {
Expand Down
19 changes: 19 additions & 0 deletions bsp/qemu-sifive-e31/metal-inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,20 @@ extern __inline__ char * __metal_driver_sifive_gpio_led_label(struct metal_led *
/* --------------------- sifive_i2c0 ------------ */


/* --------------------- sifive_pwm0 ------------ */
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm);
extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm);
extern __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx);
extern __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm);
extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm);
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm);
extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm);
extern __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm);


/* --------------------- sifive_rtc0 ------------ */
extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_base(const struct metal_rtc *const rtc);
extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_size(const struct metal_rtc *const rtc);
Expand Down Expand Up @@ -249,6 +263,11 @@ struct __metal_driver_sifive_gpio_led __metal_dt_led_2 = {
.led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
};

/* From pwm@10015000 */
struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000 = {
.pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm,
};

/* From aon@10000000 */
struct __metal_driver_sifive_rtc0 __metal_dt_rtc_10000000 = {
.rtc.vtable = &__metal_driver_vtable_sifive_rtc0.rtc,
Expand Down
Loading

0 comments on commit 59bf2c7

Please sign in to comment.