mirror of
https://github.com/LuckfoxTECH/luckfox-pico.git
synced 2026-01-18 03:28:19 +01:00
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:
@@ -6,7 +6,6 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
@@ -24,8 +23,349 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/sched_clock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/dev_printk.h>
|
||||
|
||||
#include "motor_24byj48.h"
|
||||
|
||||
#define TIMER_LOAD_COUNT0 0x00
|
||||
#define TIMER_LOAD_COUNT1 0x04
|
||||
#define TIMER_CONTROL_REG3288 0x10
|
||||
#define TIMER_CONTROL_REG3399 0x1c
|
||||
#define TIMER_INT_STATUS 0x18
|
||||
|
||||
#define TIMER_DISABLE 0x0
|
||||
#define TIMER_ENABLE 0x1
|
||||
#define TIMER_MODE_FREE_RUNNING (0 << 1)
|
||||
#define TIMER_MODE_USER_DEFINED_COUNT (1 << 1)
|
||||
#define TIMER_INT_UNMASK (1 << 2)
|
||||
|
||||
struct rk_timer {
|
||||
void __iomem *base;
|
||||
void __iomem *ctrl;
|
||||
struct clk *timer_clk;
|
||||
struct clk *pclk;
|
||||
u32 freq;
|
||||
bool skipped;
|
||||
};
|
||||
|
||||
enum motor_status {
|
||||
MOTOR_IS_STOP,
|
||||
MOTOR_IS_RUNNING,
|
||||
};
|
||||
|
||||
struct motor_reset_data {
|
||||
unsigned int x_max_steps;
|
||||
unsigned int y_max_steps;
|
||||
unsigned int reset_x;
|
||||
unsigned int reset_y;
|
||||
unsigned int x_cur_steps;
|
||||
unsigned int y_cur_steps;
|
||||
};
|
||||
|
||||
enum motor_cnt {
|
||||
HORIZONTAL_MOTOR,
|
||||
VERTICAL_MOTOR,
|
||||
HAS_MOTOR_CNT,
|
||||
};
|
||||
|
||||
struct motor_device_attribute {
|
||||
char motor_direction;
|
||||
int max_steps;
|
||||
int input_move_steps;
|
||||
int real_move_steps;
|
||||
int cur_steps;
|
||||
int motor_speed;
|
||||
int reset_point;
|
||||
ktime_t m_kt;
|
||||
unsigned int timer_count;
|
||||
int motor_gpio[MAX_GPIO_NUM];
|
||||
enum motor_status motor_current_status;
|
||||
};
|
||||
|
||||
struct motor_message {
|
||||
int x_cur_steps;
|
||||
int y_cur_steps;
|
||||
enum motor_status x_cur_status;
|
||||
enum motor_status y_cur_status;
|
||||
int x_cur_speed;
|
||||
int y_cur_speed;
|
||||
};
|
||||
|
||||
struct motors_input_steps {
|
||||
int input_x_steps;
|
||||
int input_y_steps;
|
||||
};
|
||||
|
||||
struct motors_input_speed {
|
||||
int input_x_speed;
|
||||
int input_y_speed;
|
||||
};
|
||||
|
||||
struct motors_init_data {
|
||||
struct motor_reset_data motor_data;
|
||||
struct motors_input_speed motor_speed;
|
||||
};
|
||||
|
||||
struct motor_device {
|
||||
struct proc_dir_entry *proc;
|
||||
struct miscdevice misc_dev;
|
||||
struct device *dev;
|
||||
struct mutex dev_mutex;
|
||||
spinlock_t slock;
|
||||
int motor_open_flag;
|
||||
struct rk_timer rk_timer;
|
||||
struct motor_device_attribute motors[HAS_MOTOR_CNT];
|
||||
};
|
||||
|
||||
static inline void rk_timer_disable(struct rk_timer *timer)
|
||||
{
|
||||
writel_relaxed(TIMER_DISABLE, timer->ctrl);
|
||||
}
|
||||
|
||||
static inline void rk_timer_enable(struct rk_timer *timer, u32 flags)
|
||||
{
|
||||
writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags, timer->ctrl);
|
||||
}
|
||||
|
||||
static void rk_timer_update_counter(unsigned long cycles, struct rk_timer *timer)
|
||||
{
|
||||
writel_relaxed(cycles, timer->base + TIMER_LOAD_COUNT0);
|
||||
writel_relaxed(0, timer->base + TIMER_LOAD_COUNT1);
|
||||
}
|
||||
|
||||
static void rk_timer_interrupt_clear(struct rk_timer *timer)
|
||||
{
|
||||
writel_relaxed(1, timer->base + TIMER_INT_STATUS);
|
||||
}
|
||||
|
||||
static inline int rk_timer_set_next_event(unsigned long cycles, struct rk_timer *timer)
|
||||
{
|
||||
rk_timer_disable(timer);
|
||||
rk_timer_update_counter(cycles, timer);
|
||||
rk_timer_enable(timer, TIMER_MODE_USER_DEFINED_COUNT | TIMER_INT_UNMASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int rk_timer_set_periodic(unsigned long cycles, struct rk_timer *timer)
|
||||
{
|
||||
rk_timer_disable(timer);
|
||||
rk_timer_update_counter(cycles, timer);
|
||||
rk_timer_enable(timer, TIMER_MODE_FREE_RUNNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void motor_off(struct motor_device_attribute motor)
|
||||
{
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
}
|
||||
|
||||
static int meter_turn(struct motor_device_attribute motor)
|
||||
{
|
||||
|
||||
switch (motor.timer_count) {
|
||||
case 0:
|
||||
gpio_set_value(motor.motor_gpio[0], 1);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 1:
|
||||
gpio_set_value(motor.motor_gpio[0], 1);
|
||||
gpio_set_value(motor.motor_gpio[1], 1);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 2:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 1);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 3:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 1);
|
||||
gpio_set_value(motor.motor_gpio[2], 1);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 4:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 1);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 5:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 1);
|
||||
gpio_set_value(motor.motor_gpio[3], 1);
|
||||
break;
|
||||
case 6:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 1);
|
||||
break;
|
||||
case 7:
|
||||
gpio_set_value(motor.motor_gpio[0], 1);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void motor_turn_by_id(struct motor_device *mdev, int motor_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
if (mdev->motors[motor_id].motor_direction == 'R') {
|
||||
mdev->motors[motor_id].timer_count++;
|
||||
if (mdev->motors[motor_id].timer_count > 7)
|
||||
mdev->motors[motor_id].timer_count = 0;
|
||||
} else {
|
||||
if (mdev->motors[motor_id].timer_count == 0)
|
||||
mdev->motors[motor_id].timer_count = 8;
|
||||
mdev->motors[motor_id].timer_count--;
|
||||
}
|
||||
meter_turn(mdev->motors[motor_id]);
|
||||
mdev->motors[motor_id].real_move_steps++;
|
||||
mdev->motors[motor_id].input_move_steps--;
|
||||
if (mdev->motors[motor_id].input_move_steps == 0) {
|
||||
mutex_lock(&mdev->dev_mutex);
|
||||
spin_lock_irqsave(&mdev->slock, flags);
|
||||
mdev->motors[motor_id].motor_current_status = MOTOR_IS_STOP;
|
||||
if (mdev->motors[motor_id].motor_direction == 'R')
|
||||
mdev->motors[motor_id].cur_steps = mdev->motors[motor_id].cur_steps +
|
||||
mdev->motors[motor_id].real_move_steps;
|
||||
else if (mdev->motors[motor_id].motor_direction == 'L')
|
||||
mdev->motors[motor_id].cur_steps = mdev->motors[motor_id].cur_steps -
|
||||
mdev->motors[motor_id].real_move_steps;
|
||||
mdev->motors[motor_id].input_move_steps = 0;
|
||||
mdev->motors[motor_id].real_move_steps = 0;
|
||||
spin_unlock_irqrestore(&mdev->slock, flags);
|
||||
mutex_unlock(&mdev->dev_mutex);
|
||||
printk("the motor %d steps after stop:%d\n", motor_id, mdev->motors[HORIZONTAL_MOTOR].cur_steps);
|
||||
motor_off(mdev->motors[motor_id]);
|
||||
}
|
||||
}
|
||||
|
||||
#define SECOND_IN_NS 1000000000u
|
||||
|
||||
static inline uint32_t ns_to_rktimer_cycles(uint32_t freq, uint32_t ns)
|
||||
{
|
||||
return ns / (SECOND_IN_NS / freq);
|
||||
}
|
||||
|
||||
static irqreturn_t rk_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct motor_device *mdev = dev_id;
|
||||
int next_event = 0;
|
||||
rk_timer_interrupt_clear(&mdev->rk_timer);
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].input_move_steps != 0) {
|
||||
next_event = 1;
|
||||
motor_turn_by_id(mdev, HORIZONTAL_MOTOR);
|
||||
}
|
||||
if (mdev->motors[VERTICAL_MOTOR].input_move_steps !=0) {
|
||||
next_event = 1;
|
||||
motor_turn_by_id(mdev, VERTICAL_MOTOR);
|
||||
}
|
||||
if (next_event) {
|
||||
rk_timer_set_next_event(ns_to_rktimer_cycles(mdev->rk_timer.freq, MOTOR_MAX_SPEED), &mdev->rk_timer);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rk_timer_deinit(struct motor_device *mdev)
|
||||
{
|
||||
struct rk_timer *timer = &mdev->rk_timer;
|
||||
|
||||
rk_timer_interrupt_clear(timer);
|
||||
rk_timer_disable(timer);
|
||||
|
||||
clk_disable_unprepare(timer->timer_clk);
|
||||
clk_disable_unprepare(timer->pclk);
|
||||
iounmap(timer->base);
|
||||
|
||||
};
|
||||
|
||||
static struct rk_timer *rk_timer_init(struct platform_device *pdev, struct motor_device *mdev)
|
||||
{
|
||||
struct rk_timer *timer = &mdev->rk_timer;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int ret, irq;
|
||||
|
||||
timer->base = of_iomap(np, 0);
|
||||
if (!timer->base) {
|
||||
dev_err(mdev->dev, "Failed to get base address\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
timer->ctrl = timer->base + TIMER_CONTROL_REG3288; //TODO: check 3399/3288
|
||||
|
||||
timer->pclk = of_clk_get_by_name(np, "pclk");
|
||||
if (IS_ERR(timer->pclk)) {
|
||||
dev_err(mdev->dev, "Failed to get pclk\n");
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
if (clk_prepare_enable(timer->pclk)) {
|
||||
dev_err(mdev->dev, "Failed to enable pclk\n");
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
timer->timer_clk = of_clk_get_by_name(np, "timer");
|
||||
if (IS_ERR(timer->timer_clk)) {
|
||||
dev_err(mdev->dev, "Failed to get timer clock\n");
|
||||
goto out_timer_clk;
|
||||
}
|
||||
|
||||
if (clk_prepare_enable(timer->timer_clk)) {
|
||||
dev_err(mdev->dev, "Failed to enable timer clock\n");
|
||||
goto out_timer_clk;
|
||||
}
|
||||
|
||||
timer->freq = clk_get_rate(timer->timer_clk);
|
||||
dev_info(mdev->dev, "Timer clk is %d\n", timer->freq);
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq) {
|
||||
dev_err(mdev->dev, "Failed to map interrupts for\n");
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
rk_timer_interrupt_clear(timer);
|
||||
rk_timer_disable(timer);
|
||||
|
||||
ret = devm_request_irq(mdev->dev, irq, rk_timer_interrupt,
|
||||
IRQF_TIMER, dev_name(mdev->dev), mdev);
|
||||
if (ret) {
|
||||
dev_err(mdev->dev, "Failed to initialize: %d\n", ret);
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
return timer;
|
||||
|
||||
out_irq:
|
||||
clk_disable_unprepare(timer->timer_clk);
|
||||
out_timer_clk:
|
||||
clk_disable_unprepare(timer->pclk);
|
||||
out_unmap:
|
||||
iounmap(timer->base);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void motor_set_default(struct motor_device *mdev)
|
||||
{
|
||||
int index = 0;
|
||||
@@ -44,14 +384,6 @@ static void motor_set_default(struct motor_device *mdev)
|
||||
}
|
||||
}
|
||||
|
||||
void motor_off(struct motor_device_attribute motor)
|
||||
{
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
}
|
||||
|
||||
static long motor_ops_move(struct motor_device *mdev, int x, int y)
|
||||
{
|
||||
struct motor_device_attribute *motors = mdev->motors;
|
||||
@@ -121,20 +453,7 @@ static long motor_ops_move(struct motor_device *mdev, int x, int y)
|
||||
}
|
||||
spin_unlock_irqrestore(&mdev->slock, flags);
|
||||
mutex_unlock(&mdev->dev_mutex);
|
||||
if (x1 > 0) {
|
||||
mdev->motors[HORIZONTAL_MOTOR].m_kt =
|
||||
ktime_set(0, mdev->motors[HORIZONTAL_MOTOR].motor_speed);
|
||||
hrtimer_cancel(&mdev->horizontal_motor_timer);
|
||||
hrtimer_start(&mdev->horizontal_motor_timer,
|
||||
mdev->motors[HORIZONTAL_MOTOR].m_kt, HRTIMER_MODE_REL);
|
||||
}
|
||||
if (y1 > 0) {
|
||||
mdev->motors[VERTICAL_MOTOR].m_kt =
|
||||
ktime_set(0, mdev->motors[VERTICAL_MOTOR].motor_speed);
|
||||
hrtimer_cancel(&mdev->vertical_motor_timer);
|
||||
hrtimer_start(&mdev->vertical_motor_timer,
|
||||
mdev->motors[VERTICAL_MOTOR].m_kt, HRTIMER_MODE_REL);
|
||||
}
|
||||
rk_timer_set_next_event(ns_to_rktimer_cycles(mdev->rk_timer.freq, MOTOR_MAX_SPEED), &mdev->rk_timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -151,12 +470,10 @@ static void motor_ops_stop(struct motor_device *mdev)
|
||||
return;
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].motor_current_status !=
|
||||
MOTOR_IS_STOP) {
|
||||
hrtimer_cancel(&mdev->horizontal_motor_timer);
|
||||
motor_off(mdev->motors[HORIZONTAL_MOTOR]);
|
||||
}
|
||||
if (mdev->motors[VERTICAL_MOTOR].motor_current_status !=
|
||||
MOTOR_IS_STOP) {
|
||||
hrtimer_cancel(&mdev->vertical_motor_timer);
|
||||
motor_off(mdev->motors[VERTICAL_MOTOR]);
|
||||
}
|
||||
mutex_lock(&mdev->dev_mutex);
|
||||
@@ -183,27 +500,11 @@ static int motor_speed(struct motor_device *mdev, struct motors_input_speed spee
|
||||
if ((speed.input_x_speed <= MOTOR_MIN_SPEED) &&
|
||||
(speed.input_x_speed >= MOTOR_MAX_SPEED)) {
|
||||
mdev->motors[HORIZONTAL_MOTOR].motor_speed = speed.input_x_speed;
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].motor_current_status ==
|
||||
MOTOR_IS_RUNNING) {
|
||||
mdev->motors[HORIZONTAL_MOTOR].m_kt =
|
||||
ktime_set(0, mdev->motors[HORIZONTAL_MOTOR].motor_speed);
|
||||
hrtimer_cancel(&mdev->horizontal_motor_timer);
|
||||
hrtimer_start(&mdev->horizontal_motor_timer,
|
||||
mdev->motors[HORIZONTAL_MOTOR].m_kt, HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
|
||||
if ((speed.input_y_speed <= MOTOR_MIN_SPEED) &&
|
||||
(speed.input_y_speed >= MOTOR_MAX_SPEED)) {
|
||||
mdev->motors[VERTICAL_MOTOR].motor_speed = speed.input_y_speed;
|
||||
if (mdev->motors[VERTICAL_MOTOR].motor_current_status ==
|
||||
MOTOR_IS_RUNNING) {
|
||||
mdev->motors[VERTICAL_MOTOR].m_kt =
|
||||
ktime_set(0, mdev->motors[VERTICAL_MOTOR].motor_speed);
|
||||
hrtimer_cancel(&mdev->vertical_motor_timer);
|
||||
hrtimer_start(&mdev->vertical_motor_timer,
|
||||
mdev->motors[VERTICAL_MOTOR].m_kt, HRTIMER_MODE_REL);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -266,6 +567,19 @@ static int motor_set_message(struct motor_device *mdev, struct motors_init_data
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int motor_set_calibrated_message(struct motor_device *mdev, struct motor_reset_data msg) {
|
||||
struct motor_device_attribute *motors = mdev->motors;
|
||||
|
||||
if (msg.x_cur_steps > mdev->motors[HORIZONTAL_MOTOR].max_steps ||
|
||||
msg.y_cur_steps > mdev->motors[VERTICAL_MOTOR].max_steps)
|
||||
return -1;
|
||||
|
||||
motors[HORIZONTAL_MOTOR].cur_steps = msg.x_cur_steps;
|
||||
motors[VERTICAL_MOTOR].cur_steps = msg.y_cur_steps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long motor_ops_reset(struct motor_device *mdev, struct motor_reset_data *rdata)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -373,143 +687,6 @@ static int motor_release(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meter_turn(struct motor_device_attribute motor)
|
||||
{
|
||||
|
||||
switch (motor.timer_count) {
|
||||
case 0:
|
||||
gpio_set_value(motor.motor_gpio[0], 1);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 1:
|
||||
gpio_set_value(motor.motor_gpio[0], 1);
|
||||
gpio_set_value(motor.motor_gpio[1], 1);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 2:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 1);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 3:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 1);
|
||||
gpio_set_value(motor.motor_gpio[2], 1);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 4:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 1);
|
||||
gpio_set_value(motor.motor_gpio[3], 0);
|
||||
break;
|
||||
case 5:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 1);
|
||||
gpio_set_value(motor.motor_gpio[3], 1);
|
||||
break;
|
||||
case 6:
|
||||
gpio_set_value(motor.motor_gpio[0], 0);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 1);
|
||||
break;
|
||||
case 7:
|
||||
gpio_set_value(motor.motor_gpio[0], 1);
|
||||
gpio_set_value(motor.motor_gpio[1], 0);
|
||||
gpio_set_value(motor.motor_gpio[2], 0);
|
||||
gpio_set_value(motor.motor_gpio[3], 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart motor_horizontal_timer_poll(struct hrtimer *timer)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct motor_device *mdev = container_of(timer, struct motor_device, horizontal_motor_timer);
|
||||
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].motor_direction == 'R') {
|
||||
mdev->motors[HORIZONTAL_MOTOR].timer_count++;
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].timer_count > 7)
|
||||
mdev->motors[HORIZONTAL_MOTOR].timer_count = 0;
|
||||
} else {
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].timer_count == 0)
|
||||
mdev->motors[HORIZONTAL_MOTOR].timer_count = 8;
|
||||
mdev->motors[HORIZONTAL_MOTOR].timer_count--;
|
||||
}
|
||||
meter_turn(mdev->motors[HORIZONTAL_MOTOR]);
|
||||
mdev->motors[HORIZONTAL_MOTOR].real_move_steps++;
|
||||
mdev->motors[HORIZONTAL_MOTOR].input_move_steps--;
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].input_move_steps == 0) {
|
||||
mutex_lock(&mdev->dev_mutex);
|
||||
spin_lock_irqsave(&mdev->slock, flags);
|
||||
mdev->motors[HORIZONTAL_MOTOR].motor_current_status = MOTOR_IS_STOP;
|
||||
if (mdev->motors[HORIZONTAL_MOTOR].motor_direction == 'R')
|
||||
mdev->motors[HORIZONTAL_MOTOR].cur_steps = mdev->motors[HORIZONTAL_MOTOR].cur_steps +
|
||||
mdev->motors[HORIZONTAL_MOTOR].real_move_steps;
|
||||
else if (mdev->motors[HORIZONTAL_MOTOR].motor_direction == 'L')
|
||||
mdev->motors[HORIZONTAL_MOTOR].cur_steps = mdev->motors[HORIZONTAL_MOTOR].cur_steps -
|
||||
mdev->motors[HORIZONTAL_MOTOR].real_move_steps;
|
||||
mdev->motors[HORIZONTAL_MOTOR].input_move_steps = 0;
|
||||
mdev->motors[HORIZONTAL_MOTOR].real_move_steps = 0;
|
||||
spin_unlock_irqrestore(&mdev->slock, flags);
|
||||
mutex_unlock(&mdev->dev_mutex);
|
||||
printk("the x steps after stop:%d\n", mdev->motors[HORIZONTAL_MOTOR].cur_steps);
|
||||
motor_off(mdev->motors[HORIZONTAL_MOTOR]);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
hrtimer_forward(timer, timer->base->get_time(), mdev->motors[HORIZONTAL_MOTOR].m_kt);
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart motor_vertical_timer_poll(struct hrtimer *timer)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct motor_device *mdev = container_of(timer, struct motor_device, vertical_motor_timer);
|
||||
|
||||
if (mdev->motors[VERTICAL_MOTOR].motor_direction == 'R') {
|
||||
mdev->motors[VERTICAL_MOTOR].timer_count++;
|
||||
if (mdev->motors[VERTICAL_MOTOR].timer_count > 7)
|
||||
mdev->motors[VERTICAL_MOTOR].timer_count = 0;
|
||||
} else {
|
||||
if (mdev->motors[VERTICAL_MOTOR].timer_count == 0)
|
||||
mdev->motors[VERTICAL_MOTOR].timer_count = 8;
|
||||
mdev->motors[VERTICAL_MOTOR].timer_count--;
|
||||
}
|
||||
meter_turn(mdev->motors[VERTICAL_MOTOR]);
|
||||
mdev->motors[VERTICAL_MOTOR].real_move_steps++;
|
||||
mdev->motors[VERTICAL_MOTOR].input_move_steps--;
|
||||
if (mdev->motors[VERTICAL_MOTOR].input_move_steps == 0) {
|
||||
mutex_lock(&mdev->dev_mutex);
|
||||
spin_lock_irqsave(&mdev->slock, flags);
|
||||
mdev->motors[VERTICAL_MOTOR].motor_current_status = MOTOR_IS_STOP;
|
||||
if (mdev->motors[VERTICAL_MOTOR].motor_direction == 'R')
|
||||
mdev->motors[VERTICAL_MOTOR].cur_steps = mdev->motors[VERTICAL_MOTOR].cur_steps +
|
||||
mdev->motors[VERTICAL_MOTOR].real_move_steps;
|
||||
else if (mdev->motors[VERTICAL_MOTOR].motor_direction == 'L')
|
||||
mdev->motors[VERTICAL_MOTOR].cur_steps = mdev->motors[VERTICAL_MOTOR].cur_steps -
|
||||
mdev->motors[VERTICAL_MOTOR].real_move_steps;
|
||||
mdev->motors[VERTICAL_MOTOR].input_move_steps = 0;
|
||||
mdev->motors[VERTICAL_MOTOR].real_move_steps = 0;
|
||||
spin_unlock_irqrestore(&mdev->slock, flags);
|
||||
mutex_unlock(&mdev->dev_mutex);
|
||||
printk("the y steps after stop:%d\n", mdev->motors[VERTICAL_MOTOR].cur_steps);
|
||||
motor_off(mdev->motors[VERTICAL_MOTOR]);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
hrtimer_forward(timer, timer->base->get_time(), mdev->motors[VERTICAL_MOTOR].m_kt);
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
static long motor_ioctl(struct file *file, unsigned int cmd, unsigned long value)
|
||||
{
|
||||
struct miscdevice *dev = file->private_data;
|
||||
@@ -520,7 +697,6 @@ static long motor_ioctl(struct file *file, unsigned int cmd, unsigned long value
|
||||
printk("Please Open /dev/motor Firstly\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case MOTOR_STOP: {
|
||||
motor_ops_stop(mdev);
|
||||
@@ -562,7 +738,7 @@ static long motor_ioctl(struct file *file, unsigned int cmd, unsigned long value
|
||||
return -EFAULT;
|
||||
}
|
||||
motor_ops_move(mdev, dst.input_x_steps, dst.input_y_steps);
|
||||
printk("MOTOR_MOVE!!!!!!!!!!!!!!!!!!!\n");
|
||||
//printk("MOTOR_MOVE!!!!!!!!!!!!!!!!!!!\n");
|
||||
break;
|
||||
}
|
||||
case MOTOR_GET_STATUS: {
|
||||
@@ -624,6 +800,22 @@ static long motor_ioctl(struct file *file, unsigned int cmd, unsigned long value
|
||||
/*printk("MOTOR_SET_STATUS!!!!!!!!!!!!!!!!!!\n");*/
|
||||
break;
|
||||
}
|
||||
case MOTOR_RESET_NOTCALI: {
|
||||
struct motor_reset_data data;
|
||||
if (copy_from_user(&data, (void __user *)value,
|
||||
sizeof(struct motor_reset_data))) {
|
||||
dev_err(mdev->dev, "[%s][%d] copy from user error\n",
|
||||
__func__, __LINE__);
|
||||
return -EFAULT;
|
||||
}
|
||||
printk("saved location x is %d, y is %d \n", data.x_cur_steps, data.y_cur_steps);
|
||||
ret = motor_set_calibrated_message(mdev,data);
|
||||
if (ret) {
|
||||
dev_err(mdev->dev,"motor_set_calibrated_messgae fail\n");
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -917,12 +1109,12 @@ static void motor_release_gpio(struct motor_device *mdev)
|
||||
|
||||
static int motor_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
int i = 0, index = 0;
|
||||
struct motor_device_attribute *motor = NULL;
|
||||
struct motor_device *mdev;
|
||||
struct proc_dir_entry *proc = NULL;
|
||||
struct proc_dir_entry *motor_info = NULL;
|
||||
int ret = 0;
|
||||
|
||||
printk("%s enter\n", __func__);
|
||||
mdev = devm_kzalloc(&pdev->dev, sizeof(struct motor_device), GFP_KERNEL);
|
||||
@@ -947,11 +1139,6 @@ static int motor_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "misc_register failed\n");
|
||||
}
|
||||
|
||||
hrtimer_init(&mdev->horizontal_motor_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
mdev->horizontal_motor_timer.function = motor_horizontal_timer_poll;
|
||||
hrtimer_init(&mdev->vertical_motor_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
mdev->vertical_motor_timer.function = motor_vertical_timer_poll;
|
||||
|
||||
proc = proc_mkdir("motor", NULL);
|
||||
if (!proc) {
|
||||
mdev->proc = NULL;
|
||||
@@ -982,9 +1169,16 @@ static int motor_probe(struct platform_device *pdev)
|
||||
ret = -1;
|
||||
goto motor_request_gpio_fail;
|
||||
}
|
||||
|
||||
if (rk_timer_init(pdev, mdev) == NULL) {
|
||||
printk("init timer fail\n");
|
||||
ret = -1;
|
||||
goto motor_timer_init_fail;
|
||||
}
|
||||
printk("%s leave\n", __func__);
|
||||
return 0;
|
||||
|
||||
motor_timer_init_fail:
|
||||
motor_release_gpio(mdev);
|
||||
motor_request_gpio_fail:
|
||||
if (mdev->proc)
|
||||
proc_remove(mdev->proc);
|
||||
@@ -999,7 +1193,7 @@ error_devm_kzalloc:
|
||||
static int motor_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct motor_device *mdev = platform_get_drvdata(pdev);
|
||||
|
||||
rk_timer_deinit(mdev);
|
||||
mutex_destroy(&mdev->dev_mutex);
|
||||
motor_release_gpio(mdev);
|
||||
if (mdev->proc)
|
||||
@@ -1009,8 +1203,9 @@ static int motor_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct of_device_id of_match_table = {
|
||||
.compatible = "motor"
|
||||
struct of_device_id of_match_table[] = {
|
||||
{ .compatible = "motor",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver motor_platform_driver = {
|
||||
@@ -1019,7 +1214,7 @@ static struct platform_driver motor_platform_driver = {
|
||||
.driver = {
|
||||
.name = "motor",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = &of_match_table,
|
||||
.of_match_table = of_match_ptr(of_match_table),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -26,75 +26,7 @@
|
||||
#define MOTOR_GOBACK _IOW('M', 5, long)
|
||||
#define MOTOR_CRUISE _IOW('M', 6, long)
|
||||
#define MOTOR_SET_STATUS _IOW('M', 7, long)
|
||||
|
||||
enum motor_status {
|
||||
MOTOR_IS_STOP,
|
||||
MOTOR_IS_RUNNING,
|
||||
};
|
||||
|
||||
struct motor_reset_data {
|
||||
unsigned int x_max_steps;
|
||||
unsigned int y_max_steps;
|
||||
unsigned int reset_x;
|
||||
unsigned int reset_y;
|
||||
};
|
||||
|
||||
enum motor_cnt {
|
||||
HORIZONTAL_MOTOR,
|
||||
VERTICAL_MOTOR,
|
||||
HAS_MOTOR_CNT,
|
||||
};
|
||||
|
||||
struct motor_device_attribute {
|
||||
char motor_direction;
|
||||
int max_steps;
|
||||
int input_move_steps;
|
||||
int real_move_steps;
|
||||
int cur_steps;
|
||||
int motor_speed;
|
||||
int reset_point;
|
||||
ktime_t m_kt;
|
||||
unsigned int timer_count;
|
||||
int motor_gpio[MAX_GPIO_NUM];
|
||||
enum motor_status motor_current_status;
|
||||
};
|
||||
|
||||
struct motor_message {
|
||||
int x_cur_steps;
|
||||
int y_cur_steps;
|
||||
enum motor_status x_cur_status;
|
||||
enum motor_status y_cur_status;
|
||||
int x_cur_speed;
|
||||
int y_cur_speed;
|
||||
};
|
||||
|
||||
struct motors_input_steps {
|
||||
int input_x_steps;
|
||||
int input_y_steps;
|
||||
};
|
||||
|
||||
struct motors_input_speed {
|
||||
int input_x_speed;
|
||||
int input_y_speed;
|
||||
};
|
||||
|
||||
struct motors_init_data {
|
||||
struct motor_reset_data motor_data;
|
||||
struct motors_input_speed motor_speed;
|
||||
};
|
||||
|
||||
struct motor_device {
|
||||
struct proc_dir_entry *proc;
|
||||
struct miscdevice misc_dev;
|
||||
struct device *dev;
|
||||
struct mutex dev_mutex;
|
||||
spinlock_t slock;
|
||||
int motor_open_flag;
|
||||
struct hrtimer horizontal_motor_timer;
|
||||
struct hrtimer vertical_motor_timer;
|
||||
struct motor_device_attribute motors[HAS_MOTOR_CNT];
|
||||
};
|
||||
|
||||
#define MOTOR_RESET_NOTCALI _IOW('M', 8, long)
|
||||
|
||||
#endif //__RK_MOTOR_H__
|
||||
|
||||
|
||||
Reference in New Issue
Block a user