project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.

project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
This commit is contained in:
luckfox-eng29
2024-08-21 10:05:47 +08:00
parent e79fd21975
commit 8f34c2760d
20902 changed files with 6567362 additions and 11248383 deletions

View File

@@ -181,6 +181,21 @@ config PWM_FSL_FTM
To compile this driver as a module, choose M here: the module
will be called pwm-fsl-ftm.
config PWM_GPIO
tristate "Generic GPIO bit-banged PWM driver"
depends on OF
depends on GPIOLIB
help
Some platforms do not offer any hardware PWM capabilities but do have
General Purpose Input Output (GPIO) pins available. Using the kernels
High-Resolution Timer API this driver tries to toggle GPIO using the
generic kernel PWM framework. The maximum frequency and/or accuracy
is dependent on several factors such as system load and the maximum
speed a pin can be toggled at the hardware.
To compile this driver as a module, choose M here: the module
will be called pwm-gpio.
config PWM_HIBVT
tristate "HiSilicon BVT PWM support"
depends on ARCH_HISI || COMPILE_TEST

View File

@@ -15,6 +15,7 @@ obj-$(CONFIG_PWM_CRC) += pwm-crc.o
obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
obj-$(CONFIG_PWM_GPIO) += pwm-gpio.o
obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o
obj-$(CONFIG_PWM_IMG) += pwm-img.o
obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o

View File

@@ -585,6 +585,9 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
if (state->period == pwm->state.period &&
state->duty_cycle == pwm->state.duty_cycle &&
state->polarity == pwm->state.polarity &&
#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT
state->oneshot_count == pwm->state.oneshot_count &&
#endif
state->enabled == pwm->state.enabled)
return 0;

View File

@@ -157,7 +157,6 @@ static int gpio_pwm_probe(struct platform_device *pdev)
pc->chip.npwm = 1;
pc->chip.of_xlate = of_pwm_xlate_with_flags;
pc->chip.of_pwm_n_cells = 3;
pc->chip.can_sleep = true;
pc->gpiod = devm_gpiod_get(&pdev->dev, "pwm", GPIOD_OUT_LOW);

View File

@@ -125,6 +125,7 @@ static int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (err)
return err;
duty_ns = min(duty_ns, period_ns);
val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns);
return lp3943_write_byte(lp3943, reg_duty, val);

View File

@@ -325,7 +325,6 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
{
struct lpc18xx_pwm_chip *lpc18xx_pwm;
struct pwm_device *pwm;
struct resource *res;
int ret, i;
u64 val;
@@ -336,8 +335,7 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
lpc18xx_pwm->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
lpc18xx_pwm->base = devm_ioremap_resource(&pdev->dev, res);
lpc18xx_pwm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(lpc18xx_pwm->base))
return PTR_ERR(lpc18xx_pwm->base);

View File

@@ -7,7 +7,9 @@
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -15,6 +17,9 @@
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/time.h>
#include "pwm-rockchip.h"
#define PWM_MAX_CHANNEL_NUM 4
#define PWM_CTRL_TIMER_EN (1 << 0)
#define PWM_CTRL_OUTPUT_EN (1 << 3)
@@ -32,8 +37,14 @@
#define PWM_LP_DISABLE (0 << 8)
#define PWM_ONESHOT_COUNT_SHIFT 24
#define PWM_ONESHOT_COUNT_MASK (0xff << PWM_ONESHOT_COUNT_SHIFT)
#define PWM_ONESHOT_COUNT_MAX 256
#define PWM_REG_INTSTS(n) ((3 - (n)) * 0x10 + 0x10)
#define PWM_REG_INT_EN(n) ((3 - (n)) * 0x10 + 0x14)
#define PWM_CH_INT(n) BIT(n)
struct rockchip_pwm_chip {
struct pwm_chip chip;
struct clk *clk;
@@ -46,6 +57,8 @@ struct rockchip_pwm_chip {
bool vop_pwm_en; /* indicate voppwm mirror register state */
bool center_aligned;
bool oneshot;
int channel_id;
int irq;
};
struct rockchip_pwm_regs {
@@ -103,6 +116,34 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip,
clk_disable(pc->pclk);
}
static irqreturn_t rockchip_pwm_oneshot_irq(int irq, void *data)
{
struct rockchip_pwm_chip *pc = data;
struct pwm_state state;
unsigned int id = pc->channel_id;
int val;
if (id > 3)
return IRQ_NONE;
val = readl_relaxed(pc->base + PWM_REG_INTSTS(id));
if ((val & PWM_CH_INT(id)) == 0)
return IRQ_NONE;
writel_relaxed(PWM_CH_INT(id), pc->base + PWM_REG_INTSTS(id));
/*
* Set pwm state to disabled when the oneshot mode finished.
*/
pwm_get_state(&pc->chip.pwms[0], &state);
state.enabled = false;
pwm_apply_state(&pc->chip.pwms[0], &state);
rockchip_pwm_oneshot_callback(&pc->chip.pwms[0], &state);
return IRQ_HANDLED;
}
static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
@@ -142,11 +183,24 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
pc->oneshot = false;
dev_err(chip->dev, "Oneshot_count value overflow.\n");
} else if (state->oneshot_count > 0) {
u32 int_ctrl;
pc->oneshot = true;
ctrl &= ~PWM_ONESHOT_COUNT_MASK;
ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT;
int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id));
int_ctrl |= PWM_CH_INT(pc->channel_id);
writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id));
} else {
u32 int_ctrl;
pc->oneshot = false;
ctrl |= PWM_CONTINUOUS;
int_ctrl = readl_relaxed(pc->base + PWM_REG_INT_EN(pc->channel_id));
int_ctrl &= ~PWM_CH_INT(pc->channel_id);
writel_relaxed(int_ctrl, pc->base + PWM_REG_INT_EN(pc->channel_id));
}
#endif
@@ -335,6 +389,13 @@ static const struct of_device_id rockchip_pwm_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
static int rockchip_pwm_get_channel_id(const char *name)
{
int len = strlen(name);
return name[len - 2] - '0';
}
static int rockchip_pwm_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
@@ -392,16 +453,42 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
goto err_clk;
}
pc->channel_id = rockchip_pwm_get_channel_id(pdev->dev.of_node->full_name);
if (pc->channel_id < 0 || pc->channel_id >= PWM_MAX_CHANNEL_NUM) {
dev_err(&pdev->dev, "Channel id is out of range: %d\n", pc->channel_id);
ret = -EINVAL;
goto err_pclk;
}
if (IS_ENABLED(CONFIG_PWM_ROCKCHIP_ONESHOT)) {
pc->irq = platform_get_irq(pdev, 0);
if (pc->irq < 0) {
dev_err(&pdev->dev, "Get oneshot mode irq failed\n");
ret = pc->irq;
goto err_pclk;
}
ret = devm_request_irq(&pdev->dev, pc->irq, rockchip_pwm_oneshot_irq,
IRQF_NO_SUSPEND | IRQF_SHARED,
"rk_pwm_oneshot_irq", pc);
if (ret) {
dev_err(&pdev->dev, "Claim oneshot IRQ failed\n");
goto err_pclk;
}
}
pc->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(pc->pinctrl)) {
dev_err(&pdev->dev, "Get pinctrl failed!\n");
return PTR_ERR(pc->pinctrl);
ret = PTR_ERR(pc->pinctrl);
goto err_pclk;
}
pc->active_state = pinctrl_lookup_state(pc->pinctrl, "active");
if (IS_ERR(pc->active_state)) {
dev_err(&pdev->dev, "No active pinctrl state\n");
return PTR_ERR(pc->active_state);
ret = PTR_ERR(pc->active_state);
goto err_pclk;
}
platform_set_drvdata(pdev, pc);

View File

@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
*/
#ifndef _PWM_ROCKCHIP_H_
#define _PWM_ROCKCHIP_H_
#include <linux/pwm.h>
static void rockchip_pwm_oneshot_callback(struct pwm_device *pwm, struct pwm_state *state)
{
/*
* If you want to enable oneshot mode again, config and call
* pwm_apply_state().
*
* struct pwm_state new_state;
*
* pwm_get_state(pwm, &new_state);
* new_state.enabled = true;
* ......
* pwm_apply_state(pwm, &new_state);
*
*/
}
#endif

View File

@@ -23,7 +23,7 @@
#define PWM_SIFIVE_PWMCFG 0x0
#define PWM_SIFIVE_PWMCOUNT 0x8
#define PWM_SIFIVE_PWMS 0x10
#define PWM_SIFIVE_PWMCMP0 0x20
#define PWM_SIFIVE_PWMCMP(i) (0x20 + 4 * (i))
/* PWMCFG fields */
#define PWM_SIFIVE_PWMCFG_SCALE GENMASK(3, 0)
@@ -36,8 +36,6 @@
#define PWM_SIFIVE_PWMCFG_GANG BIT(24)
#define PWM_SIFIVE_PWMCFG_IP BIT(28)
/* PWM_SIFIVE_SIZE_PWMCMP is used to calculate offset for pwmcmpX registers */
#define PWM_SIFIVE_SIZE_PWMCMP 4
#define PWM_SIFIVE_CMPWIDTH 16
#define PWM_SIFIVE_DEFAULT_PERIOD 10000000
@@ -112,8 +110,7 @@ static void pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip);
u32 duty, val;
duty = readl(ddata->regs + PWM_SIFIVE_PWMCMP0 +
pwm->hwpwm * PWM_SIFIVE_SIZE_PWMCMP);
duty = readl(ddata->regs + PWM_SIFIVE_PWMCMP(pwm->hwpwm));
state->enabled = duty > 0;
@@ -194,8 +191,7 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,
pwm_sifive_update_clock(ddata, clk_get_rate(ddata->clk));
}
writel(frac, ddata->regs + PWM_SIFIVE_PWMCMP0 +
pwm->hwpwm * PWM_SIFIVE_SIZE_PWMCMP);
writel(frac, ddata->regs + PWM_SIFIVE_PWMCMP(pwm->hwpwm));
if (state->enabled != enabled)
pwm_sifive_enable(chip, state->enabled);
@@ -234,6 +230,8 @@ static int pwm_sifive_probe(struct platform_device *pdev)
struct pwm_chip *chip;
struct resource *res;
int ret;
u32 val;
unsigned int enabled_pwms = 0, enabled_clks = 1;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
@@ -264,6 +262,33 @@ static int pwm_sifive_probe(struct platform_device *pdev)
return ret;
}
val = readl(ddata->regs + PWM_SIFIVE_PWMCFG);
if (val & PWM_SIFIVE_PWMCFG_EN_ALWAYS) {
unsigned int i;
for (i = 0; i < chip->npwm; ++i) {
val = readl(ddata->regs + PWM_SIFIVE_PWMCMP(i));
if (val > 0)
++enabled_pwms;
}
}
/* The clk should be on once for each running PWM. */
if (enabled_pwms) {
while (enabled_clks < enabled_pwms) {
/* This is not expected to fail as the clk is already on */
ret = clk_enable(ddata->clk);
if (unlikely(ret)) {
dev_err_probe(dev, ret, "Failed to enable clk\n");
goto disable_clk;
}
++enabled_clks;
}
} else {
clk_disable(ddata->clk);
enabled_clks = 0;
}
/* Watch for changes to underlying clock frequency */
ddata->notifier.notifier_call = pwm_sifive_clock_notifier;
ret = clk_notifier_register(ddata->clk, &ddata->notifier);
@@ -286,7 +311,11 @@ static int pwm_sifive_probe(struct platform_device *pdev)
unregister_clk:
clk_notifier_unregister(ddata->clk, &ddata->notifier);
disable_clk:
clk_disable_unprepare(ddata->clk);
while (enabled_clks) {
clk_disable(ddata->clk);
--enabled_clks;
}
clk_unprepare(ddata->clk);
return ret;
}
@@ -294,25 +323,21 @@ disable_clk:
static int pwm_sifive_remove(struct platform_device *dev)
{
struct pwm_sifive_ddata *ddata = platform_get_drvdata(dev);
bool is_enabled = false;
struct pwm_device *pwm;
int ret, ch;
int ch;
pwmchip_remove(&ddata->chip);
clk_notifier_unregister(ddata->clk, &ddata->notifier);
for (ch = 0; ch < ddata->chip.npwm; ch++) {
pwm = &ddata->chip.pwms[ch];
if (pwm->state.enabled) {
is_enabled = true;
break;
}
if (pwm->state.enabled)
clk_disable(ddata->clk);
}
if (is_enabled)
clk_disable(ddata->clk);
clk_disable_unprepare(ddata->clk);
ret = pwmchip_remove(&ddata->chip);
clk_notifier_unregister(ddata->clk, &ddata->notifier);
clk_unprepare(ddata->clk);
return ret;
return 0;
}
static const struct of_device_id pwm_sifive_of_match[] = {