111 lines
2.7 KiB
C
111 lines
2.7 KiB
C
#include <linux/kernel.h>
|
|
#include <linux/etherdevice.h>
|
|
#include "gsc3280mac_timer.h"
|
|
|
|
static void gsc3280mac_timer_handler(void *data)
|
|
{
|
|
struct net_device *dev = (struct net_device *)data;
|
|
|
|
gsc3280mac_schedule(dev);
|
|
}
|
|
|
|
#define GSC3280MAC_TIMER_MSG(timer, freq) \
|
|
printk(KERN_INFO "gsc3280mac_timer: %s Timer ON (freq %dHz)\n", timer, freq);
|
|
|
|
#if defined(CONFIG_GSC3280MAC_RTC_TIMER)
|
|
#include <linux/rtc.h>
|
|
static struct rtc_device *gsc3280mac_rtc;
|
|
static rtc_task_t gsc3280mac_task;
|
|
|
|
static void gsc3280mac_rtc_start(unsigned int new_freq)
|
|
{
|
|
rtc_irq_set_freq(gsc3280mac_rtc, &gsc3280mac_task, new_freq);
|
|
rtc_irq_set_state(gsc3280mac_rtc, &gsc3280mac_task, 1);
|
|
}
|
|
|
|
static void gsc3280mac_rtc_stop(void)
|
|
{
|
|
rtc_irq_set_state(gsc3280mac_rtc, &gsc3280mac_task, 0);
|
|
}
|
|
|
|
int gsc3280mac_open_ext_timer(struct net_device *dev, struct gsc3280mac_timer *tm)
|
|
{
|
|
gsc3280mac_task.private_data = dev;
|
|
gsc3280mac_task.func = gsc3280mac_timer_handler;
|
|
|
|
gsc3280mac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
|
|
if (gsc3280mac_rtc == NULL) {
|
|
pr_err("open rtc device failed\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
rtc_irq_register(gsc3280mac_rtc, &gsc3280mac_task);
|
|
|
|
/* Periodic mode is not supported */
|
|
if ((rtc_irq_set_freq(gsc3280mac_rtc, &gsc3280mac_task, tm->freq) < 0)) {
|
|
pr_err("set periodic failed\n");
|
|
rtc_irq_unregister(gsc3280mac_rtc, &gsc3280mac_task);
|
|
rtc_class_close(gsc3280mac_rtc);
|
|
return -1;
|
|
}
|
|
|
|
GSC3280MAC_TIMER_MSG(CONFIG_RTC_HCTOSYS_DEVICE, tm->freq);
|
|
|
|
tm->timer_start = gsc3280mac_rtc_start;
|
|
tm->timer_stop = gsc3280mac_rtc_stop;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int gsc3280mac_close_ext_timer(void)
|
|
{
|
|
rtc_irq_set_state(gsc3280mac_rtc, &gsc3280mac_task, 0);
|
|
rtc_irq_unregister(gsc3280mac_rtc, &gsc3280mac_task);
|
|
rtc_class_close(gsc3280mac_rtc);
|
|
return 0;
|
|
}
|
|
|
|
#elif defined(CONFIG_GSC3280MAC_TMU_TIMER)
|
|
#include <linux/clk.h>
|
|
#define TMU_CHANNEL "tmu2_clk"
|
|
static struct clk *timer_clock;
|
|
|
|
static void gsc3280mac_tmu_start(unsigned int new_freq)
|
|
{
|
|
clk_set_rate(timer_clock, new_freq);
|
|
clk_enable(timer_clock);
|
|
}
|
|
|
|
static void gsc3280mac_tmu_stop(void)
|
|
{
|
|
clk_disable(timer_clock);
|
|
}
|
|
|
|
int gsc3280mac_open_ext_timer(struct net_device *dev, struct gsc3280mac_timer *tm)
|
|
{
|
|
timer_clock = clk_get(NULL, TMU_CHANNEL);
|
|
|
|
if (timer_clock == NULL)
|
|
return -1;
|
|
|
|
if (tmu2_register_user(gsc3280mac_timer_handler, (void *)dev) < 0) {
|
|
timer_clock = NULL;
|
|
return -1;
|
|
}
|
|
|
|
GSC3280MAC_TIMER_MSG("TMU2", tm->freq);
|
|
tm->timer_start = gsc3280mac_tmu_start;
|
|
tm->timer_stop = gsc3280mac_tmu_stop;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int gsc3280mac_close_ext_timer(void)
|
|
{
|
|
clk_disable(timer_clock);
|
|
tmu2_unregister_user();
|
|
clk_put(timer_clock);
|
|
return 0;
|
|
}
|
|
#endif
|