Skip to content

Commit 3750141

Browse files
committed
[bsp/raspberry-pi] update DM support
- reorganize common Raspberry Pi drivers under the device framework - add the Raspberry Pi 5 BSP, configuration and documentation - add BCM2712 and DesignWare AXI DMA controller support - distinguish BCM2712 DMA32 and DMA40 channels by channel mask - restore DesignWare AXI DMA enable bits after controller reset - support a shared AXI maximum burst length across DMA channels Signed-off-by: GuEe-GUI <2991707448@qq.com>
1 parent 76b0267 commit 3750141

264 files changed

Lines changed: 35894 additions & 17631 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bsp/raspberry-pi/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
kernel*.img
2+
rtthread.bin
3+
*.dtb
4+
*.qcow2
5+
flash.bin
6+
rtt.asm
7+
rtthread.map
8+
build/

bsp/raspberry-pi/dm/Kconfig

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
SOC_DM_ADC_DIR = $(SOC_DM_DIR)/adc
2+
SOC_DM_AUDIO_DIR = $(SOC_DM_DIR)/audio
3+
SOC_DM_CLK_DIR = $(SOC_DM_DIR)/clk
4+
SOC_DM_DMA_DIR = $(SOC_DM_DIR)/dma
5+
SOC_DM_DVFS_CPUFREQ_DIR = $(SOC_DM_DIR)/dvfs
6+
SOC_DM_ETHERNET_DIR = $(SOC_DM_DIR)/ethernet
7+
SOC_DM_FIRMWARE_DIR = $(SOC_DM_DIR)/firmware
8+
SOC_DM_GRAPHIC_BACKLIGHT_DIR = $(SOC_DM_DIR)/graphic/backlight
9+
SOC_DM_GRAPHIC_FB_DIR = $(SOC_DM_DIR)/graphic/framebuffer
10+
SOC_DM_GRAPHIC_LOGO_DIR = $(SOC_DM_DIR)/graphic/logo
11+
SOC_DM_HWCRYPTO_DIR = $(SOC_DM_DIR)/hwcrypto
12+
SOC_DM_CLOCK_TIME_DIR = $(SOC_DM_DIR)/clock_time
13+
SOC_DM_I2C_DIR = $(SOC_DM_DIR)/i2c
14+
SOC_DM_INPUT_JOYSTICK_DIR = $(SOC_DM_DIR)/input/joystick
15+
SOC_DM_INPUT_TOUCHSCREEN_DIR = $(SOC_DM_DIR)/input/touchscreen
16+
SOC_DM_MBOX_DIR = $(SOC_DM_DIR)/mailbox
17+
SOC_DM_MFD_DIR = $(SOC_DM_DIR)/mfd
18+
SOC_DM_NVMEM_DIR = $(SOC_DM_DIR)/nvmem
19+
SOC_DM_PCI_DIR = $(SOC_DM_DIR)/pci
20+
SOC_DM_PHY_DIR = $(SOC_DM_DIR)/phy
21+
SOC_DM_PIC_DIR = $(SOC_DM_DIR)/pic
22+
SOC_DM_PIN_DIR = $(SOC_DM_DIR)/pin
23+
SOC_DM_PINCTRL_DIR = $(SOC_DM_DIR)/pinctrl
24+
SOC_DM_PMDOMAIN_DIR = $(SOC_DM_DIR)/pmdomain
25+
SOC_DM_PWM_DIR = $(SOC_DM_DIR)/pwm
26+
SOC_DM_RESET_DIR = $(SOC_DM_DIR)/reset
27+
SOC_DM_RTC_DIR = $(SOC_DM_DIR)/rtc
28+
SOC_DM_SDIO_DIR = $(SOC_DM_DIR)/sdio
29+
SOC_DM_SERIAL_DIR = $(SOC_DM_DIR)/serial
30+
SOC_DM_SOC_DIR = $(SOC_DM_DIR)/soc
31+
SOC_DM_SPI_DIR = $(SOC_DM_DIR)/spi
32+
SOC_DM_THERMAL_DIR = $(SOC_DM_DIR)/thermal
33+
SOC_DM_WDT_DIR = $(SOC_DM_DIR)/watchdog
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# for module compiling
21
import os
32
from building import *
43

bsp/raspberry-pi/dm/adc/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
config RT_ADC_RP1
2+
bool "RP1 ADC and temperature sensor driver"
3+
depends on RT_USING_DM
4+
depends on RT_USING_ADC
5+
depends on RT_USING_REGULATOR
6+
default n

bsp/raspberry-pi/dm/adc/SConscript

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from building import *
2+
3+
group = []
4+
src = []
5+
cwd = GetCurrentDir()
6+
CPPPATH = [cwd + '/../include']
7+
8+
if GetDepend(['RT_ADC_RP1']):
9+
src += ['adc-rp1.c']
10+
11+
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
12+
13+
Return('group')

bsp/raspberry-pi/dm/adc/adc-rp1.c

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
/*
2+
* Copyright (c) 2006-2023, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2023-11-25 GuEe-GUI first version
9+
*/
10+
11+
#include <rthw.h>
12+
#include <rtthread.h>
13+
#include <rtdevice.h>
14+
15+
#define RP1_ADC_CS 0x00
16+
#define RP1_ADC_RESULT 0x04
17+
#define RP1_ADC_FCS 0x08
18+
#define RP1_ADC_FIFO 0x0c
19+
#define RP1_ADC_DIV 0x10
20+
21+
#define RP1_ADC_INTR 0x14
22+
#define RP1_ADC_INTE 0x18
23+
#define RP1_ADC_INTF 0x1c
24+
#define RP1_ADC_INTS 0x20
25+
26+
#define RP1_ADC_RWTYPE_SET 0x2000
27+
#define RP1_ADC_RWTYPE_CLR 0x3000
28+
29+
#define RP1_ADC_CS_RROBIN_MASK 0x1f
30+
#define RP1_ADC_CS_RROBIN_SHIFT 16
31+
#define RP1_ADC_CS_AINSEL_MASK 0x7
32+
#define RP1_ADC_CS_AINSEL_SHIFT 12
33+
#define RP1_ADC_CS_ERR_STICKY 0x400
34+
#define RP1_ADC_CS_ERR 0x200
35+
#define RP1_ADC_CS_READY 0x100
36+
#define RP1_ADC_CS_START_MANY 0x8
37+
#define RP1_ADC_CS_START_ONCE 0x4
38+
#define RP1_ADC_CS_TS_EN 0x2
39+
#define RP1_ADC_CS_EN 0x1
40+
41+
#define RP1_ADC_FCS_THRESH_MASK 0xf
42+
#define RP1_ADC_FCS_THRESH_SHIFT 24
43+
#define RP1_ADC_FCS_LEVEL_MASK 0xf
44+
#define RP1_ADC_FCS_LEVEL_SHIFT 16
45+
#define RP1_ADC_FCS_OVER 0x800
46+
#define RP1_ADC_FCS_UNDER 0x400
47+
#define RP1_ADC_FCS_FULL 0x200
48+
#define RP1_ADC_FCS_EMPTY 0x100
49+
#define RP1_ADC_FCS_DREQ_EN 0x8
50+
#define RP1_ADC_FCS_ERR 0x4
51+
#define RP1_ADC_FCS_SHIFR 0x2
52+
#define RP1_ADC_FCS_EN 0x1
53+
54+
#define RP1_ADC_FIFO_ERR 0x8000
55+
#define RP1_ADC_FIFO_VAL_MASK 0xfff
56+
57+
#define RP1_ADC_DIV_INT_MASK 0xffff
58+
#define RP1_ADC_DIV_INT_SHIFT 8
59+
#define RP1_ADC_DIV_FRAC_MASK 0xff
60+
#define RP1_ADC_DIV_FRAC_SHIFT 0
61+
62+
enum
63+
{
64+
RP1_ADC_IN,
65+
RP1_ADC_RAW,
66+
RP1_ADC_TEMP,
67+
};
68+
69+
struct rp1_adc_channel
70+
{
71+
rt_uint32_t type;
72+
73+
const char *name;
74+
};
75+
76+
struct rp1_adc
77+
{
78+
struct rt_adc_device parent;
79+
80+
void *regs;
81+
int vref_mv;
82+
83+
struct rt_clk *clk;
84+
struct rt_regulator *vref;
85+
86+
rt_size_t channel_nr;
87+
struct rp1_adc_channel *channel;
88+
89+
struct rt_spinlock lock;
90+
};
91+
92+
#define raw_to_rp1_adc(raw) rt_container_of(raw, struct rp1_adc, parent)
93+
94+
static rt_err_t rp1_adc_ready_wait(struct rp1_adc *radc)
95+
{
96+
int retries = 10;
97+
98+
while (retries && !(HWREG32(radc->regs + RP1_ADC_CS) & RP1_ADC_CS_READY))
99+
{
100+
--retries;
101+
}
102+
103+
return retries ? 0 : -RT_EIO;
104+
}
105+
106+
static rt_err_t rp1_adc_read(struct rp1_adc *radc, int channel, rt_uint32_t *val)
107+
{
108+
rt_err_t err;
109+
110+
rt_hw_spin_lock(&radc->lock.lock);
111+
112+
HWREG32(radc->regs + RP1_ADC_RWTYPE_CLR + RP1_ADC_CS) =
113+
RP1_ADC_CS_AINSEL_MASK << RP1_ADC_CS_AINSEL_SHIFT;
114+
HWREG32(radc->regs + RP1_ADC_RWTYPE_SET + RP1_ADC_CS) =
115+
channel << RP1_ADC_CS_AINSEL_SHIFT;
116+
HWREG32(radc->regs + RP1_ADC_RWTYPE_SET + RP1_ADC_CS) =
117+
RP1_ADC_CS_START_ONCE;
118+
119+
if ((err = rp1_adc_ready_wait(radc)))
120+
{
121+
goto _out_lock;
122+
}
123+
124+
/* Asserted if the completed conversion had a convergence error */
125+
if (HWREG32(radc->regs + RP1_ADC_CS) & RP1_ADC_CS_ERR)
126+
{
127+
err = -RT_EIO;
128+
goto _out_lock;
129+
}
130+
131+
*val = HWREG32(radc->regs + RP1_ADC_RESULT);
132+
133+
_out_lock:
134+
rt_hw_spin_unlock(&radc->lock.lock);
135+
136+
return err;
137+
}
138+
139+
static int rp1_adc_to_mv(struct rp1_adc *radc, rt_uint32_t val)
140+
{
141+
return ((rt_uint64_t)radc->vref_mv * val) / 0xfff;
142+
}
143+
144+
static struct rp1_adc_channel adc_channel[] =
145+
{
146+
{ .type = RP1_ADC_IN, .name = "in1-input" },
147+
{ .type = RP1_ADC_IN, .name = "in2-input" },
148+
{ .type = RP1_ADC_IN, .name = "in3-input" },
149+
{ .type = RP1_ADC_IN, .name = "in4-input" },
150+
{ .type = RP1_ADC_TEMP, .name = "temp1-input" },
151+
{ .type = RP1_ADC_RAW, .name = "in1-raw" },
152+
{ .type = RP1_ADC_RAW, .name = "in2-raw" },
153+
{ .type = RP1_ADC_RAW, .name = "in3-raw" },
154+
{ .type = RP1_ADC_RAW, .name = "in4-raw" },
155+
{ .type = RP1_ADC_RAW, .name = "temp1-raw" },
156+
};
157+
158+
static rt_err_t rp1_adc_enabled(struct rt_adc_device *adc, rt_int8_t channel, rt_bool_t enabled)
159+
{
160+
return RT_EOK;
161+
}
162+
163+
static rt_err_t rp1_adc_convert(struct rt_adc_device *adc, rt_int8_t channel, rt_uint32_t *value)
164+
{
165+
rt_err_t err;
166+
rt_uint32_t val;
167+
struct rp1_adc_channel *chan;
168+
struct rp1_adc *radc = raw_to_rp1_adc(adc);
169+
170+
if (channel >= radc->channel_nr)
171+
{
172+
return -RT_EINVAL;
173+
}
174+
175+
chan = &radc->channel[channel];
176+
177+
if (chan->type == RP1_ADC_TEMP)
178+
{
179+
int mv;
180+
181+
HWREG32(radc->regs + RP1_ADC_RWTYPE_SET + RP1_ADC_CS) = RP1_ADC_CS_TS_EN;
182+
183+
if ((err = rp1_adc_read(radc, channel, &val)))
184+
{
185+
return err;
186+
}
187+
188+
mv = rp1_adc_to_mv(radc, val);
189+
190+
/* T = 27 - (ADC_voltage - 0.706)/0.001721 */
191+
192+
*value = 27000 - RT_DIV_ROUND_CLOSEST((mv - 706) * (rt_int64_t)1000000, 1721);
193+
}
194+
else if (chan->type == RP1_ADC_IN || chan->type == RP1_ADC_RAW)
195+
{
196+
if ((err = rp1_adc_read(radc, channel, &val)))
197+
{
198+
return err;
199+
}
200+
201+
*value = val;
202+
}
203+
204+
return RT_EOK;
205+
}
206+
207+
static const struct rt_adc_ops rp1_adc_ops =
208+
{
209+
.enabled = rp1_adc_enabled,
210+
.convert = rp1_adc_convert,
211+
};
212+
213+
static void rp1_adc_free(struct rp1_adc *radc)
214+
{
215+
if (radc->regs)
216+
{
217+
rt_iounmap(radc->regs);
218+
}
219+
220+
if (!rt_is_err_or_null(radc->clk))
221+
{
222+
rt_clk_disable_unprepare(radc->clk);
223+
rt_clk_put(radc->clk);
224+
}
225+
226+
rt_free(radc);
227+
}
228+
229+
static rt_err_t rp1_adc_probe(struct rt_platform_device *pdev)
230+
{
231+
int vref_uv;
232+
rt_err_t err;
233+
const char *dev_name;
234+
struct rt_device *dev = &pdev->parent;
235+
struct rp1_adc *radc = rt_calloc(1, sizeof(*radc));
236+
237+
if (!radc)
238+
{
239+
return -RT_ENOMEM;
240+
}
241+
242+
radc->regs = rt_dm_dev_iomap(dev, 0);
243+
244+
if (!radc->regs)
245+
{
246+
err = -RT_EIO;
247+
goto _fail;
248+
}
249+
250+
radc->clk = rt_clk_get_by_index(dev, 0);
251+
252+
if (rt_is_err(radc->clk))
253+
{
254+
err = rt_ptr_err(radc->clk);
255+
goto _fail;
256+
}
257+
258+
rt_clk_set_rate(radc->clk, 50000000);
259+
rt_clk_prepare_enable(radc->clk);
260+
261+
radc->vref = rt_regulator_get(dev, "vref");
262+
263+
if (rt_is_err(radc->vref))
264+
{
265+
err = rt_ptr_err(radc->vref);
266+
goto _fail;
267+
}
268+
269+
vref_uv = rt_regulator_get_voltage(radc->vref);
270+
radc->vref_mv = RT_DIV_ROUND_CLOSEST(vref_uv, 1000);
271+
272+
radc->channel_nr = RT_ARRAY_SIZE(adc_channel);
273+
radc->channel = adc_channel;
274+
275+
rt_spin_lock_init(&radc->lock);
276+
277+
dev->user_data = radc;
278+
279+
rt_dm_dev_set_name_auto(&radc->parent.parent, "adc");
280+
dev_name = rt_dm_dev_get_name(&radc->parent.parent);
281+
282+
rt_hw_adc_register(&radc->parent, dev_name, &rp1_adc_ops, radc);
283+
284+
rt_dm_dev_bind_fwdata(dev, RT_NULL, radc);
285+
286+
/* Disable interrupts */
287+
HWREG32(radc->regs + RP1_ADC_INTE) = 0;
288+
289+
/* Enable the block, clearing any sticky error */
290+
HWREG32(radc->regs + RP1_ADC_CS) = RP1_ADC_CS_EN | RP1_ADC_CS_ERR_STICKY;
291+
292+
return RT_EOK;
293+
294+
_fail:
295+
rp1_adc_free(radc);
296+
297+
return err;
298+
}
299+
300+
static rt_err_t rp1_adc_remove(struct rt_platform_device *pdev)
301+
{
302+
struct rt_device *dev = &pdev->parent;
303+
struct rp1_adc *radc = dev->user_data;
304+
305+
rt_dm_dev_unbind_fwdata(dev, RT_NULL);
306+
307+
rt_device_unregister(&radc->parent.parent);
308+
309+
rp1_adc_free(radc);
310+
311+
return RT_EOK;
312+
}
313+
314+
static const struct rt_ofw_node_id rp1_adc_ofw_ids[] =
315+
{
316+
{ .compatible = "raspberrypi,rp1-adc" },
317+
{ /* sentinel */ }
318+
};
319+
320+
static struct rt_platform_driver rp1_adc_driver =
321+
{
322+
.name = "rp1-adc",
323+
.ids = rp1_adc_ofw_ids,
324+
325+
.probe = rp1_adc_probe,
326+
.remove = rp1_adc_remove,
327+
};
328+
RT_PLATFORM_DRIVER_EXPORT(rp1_adc_driver);

0 commit comments

Comments
 (0)