static irqreturn_t mfgpt_tick(int irq, void *dev_id)
{
	uint16_t val = cs5535_mfgpt_read(cs5535_event_clock, MFGPT_REG_SETUP);

	/* See if the interrupt was for us */
	if (!(val & (MFGPT_SETUP_SETUP | MFGPT_SETUP_CMP2 | MFGPT_SETUP_CMP1)))
		return IRQ_NONE;

	/* Turn off the clock (and clear the event) */
	disable_timer(cs5535_event_clock);

	if (cs5535_tick_mode == CLOCK_EVT_MODE_SHUTDOWN)
		return IRQ_HANDLED;

	/* Clear the counter */
	cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_COUNTER, 0);

	/* Restart the clock in periodic mode */

	if (cs5535_tick_mode == CLOCK_EVT_MODE_PERIODIC)
		cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP,
				MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2);

	cs5535_clockevent.event_handler(&cs5535_clockevent);
	return IRQ_HANDLED;
}
static void start_timer(struct cs5535_mfgpt_timer *timer, uint16_t delta)
{
	cs5535_mfgpt_write(timer, MFGPT_REG_CMP2, delta);
	cs5535_mfgpt_write(timer, MFGPT_REG_COUNTER, 0);

	cs5535_mfgpt_write(timer, MFGPT_REG_SETUP,
			MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2);
}
Ejemplo n.º 3
0
static int ot200_backlight_probe(struct platform_device *pdev)
{
	struct backlight_device *bl;
	struct ot200_backlight_data *data;
	struct backlight_properties props;
	int retval = 0;

	/* request gpio */
	if (devm_gpio_request(&pdev->dev, GPIO_DIMM,
				"ot200 backlight dimmer") < 0) {
		dev_err(&pdev->dev, "failed to request GPIO %d\n", GPIO_DIMM);
		return -ENODEV;
	}

	/* request timer */
	pwm_timer = cs5535_mfgpt_alloc_timer(7, MFGPT_DOMAIN_ANY);
	if (!pwm_timer) {
		dev_err(&pdev->dev, "MFGPT 7 not available\n");
		return -ENODEV;
	}

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data) {
		retval = -ENOMEM;
		goto error_devm_kzalloc;
	}

	/* setup gpio */
	cs5535_gpio_set(GPIO_DIMM, GPIO_OUTPUT_ENABLE);
	cs5535_gpio_set(GPIO_DIMM, GPIO_OUTPUT_AUX1);

	/* setup timer */
	cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1, 0);
	cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP2, MAX_COMP2);
	cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, PWM_SETUP);

	data->current_brightness = 100;
	props.max_brightness = 100;
	props.brightness = 100;
	props.type = BACKLIGHT_RAW;

	bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev),
					&pdev->dev, data, &ot200_backlight_ops,
					&props);
	if (IS_ERR(bl)) {
		dev_err(&pdev->dev, "failed to register backlight\n");
		retval = PTR_ERR(bl);
		goto error_devm_kzalloc;
	}

	platform_set_drvdata(pdev, bl);

	return 0;

error_devm_kzalloc:
	cs5535_mfgpt_free_timer(pwm_timer);
	return retval;
}
Ejemplo n.º 4
0
static void geodewdt_ping(void)
{
	/* Stop the counter */
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);

	/* Reset the counter */
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);

	/* Enable the counter */
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
}
Ejemplo n.º 5
0
static void geodewdt_ping(void)
{

    cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);


    cs5535_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);


    cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
}
Ejemplo n.º 6
0
static int ot200_backlight_remove(struct platform_device *pdev)
{
	/* on module unload set brightness to 100% */
	cs5535_mfgpt_write(pwm_timer, MFGPT_REG_COUNTER, 0);
	cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);
	cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1,
		MAX_COMP2 - dim_table[100]);

	cs5535_mfgpt_free_timer(pwm_timer);

	return 0;
}
Ejemplo n.º 7
0
static int geodewdt_set_heartbeat(int val)
{
	if (val < 1 || val > GEODEWDT_MAX_SECONDS)
		return -EINVAL;

	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, val * GEODEWDT_HZ);
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN);

	timeout = val;
	return 0;
}
static void disable_timer(struct cs5535_mfgpt_timer *timer)
{
	/* avoid races by clearing CMP1 and CMP2 unconditionally */
	cs5535_mfgpt_write(timer, MFGPT_REG_SETUP,
			(uint16_t) ~MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP1 |
				MFGPT_SETUP_CMP2);
}
Ejemplo n.º 9
0
static int __init cs5535_mfgpt_init(void)
{
	struct cs5535_mfgpt_timer *timer;
	int ret;
	uint16_t val;

	timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
	if (!timer) {
		printk(KERN_ERR DRV_NAME ": Could not allocate MFPGT timer\n");
		return -ENODEV;
	}
	cs5535_event_clock = timer;

	/* Set up the IRQ on the MFGPT side */
	if (cs5535_mfgpt_setup_irq(timer, MFGPT_CMP2, &timer_irq)) {
		printk(KERN_ERR DRV_NAME ": Could not set up IRQ %d\n",
				timer_irq);
		goto err_timer;
	}

	/* And register it with the kernel */
	ret = setup_irq(timer_irq, &mfgptirq);
	if (ret) {
		printk(KERN_ERR DRV_NAME ": Unable to set up the interrupt.\n");
		goto err_irq;
	}

	/* Set the clock scale and enable the event mode for CMP2 */
	val = MFGPT_SCALE | (3 << 8);

	cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, val);

	/* Set up the clock event */
	cs5535_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC,
			cs5535_clockevent.shift);
	cs5535_clockevent.min_delta_ns = clockevent_delta2ns(0xF,
			&cs5535_clockevent);
	cs5535_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE,
			&cs5535_clockevent);

	printk(KERN_INFO DRV_NAME
		": Registering MFGPT timer as a clock event, using IRQ %d\n",
		timer_irq);
	clockevents_register_device(&cs5535_clockevent);

	return 0;

err_irq:
	cs5535_mfgpt_release_irq(cs5535_event_clock, MFGPT_CMP2, &timer_irq);
err_timer:
	cs5535_mfgpt_free_timer(cs5535_event_clock);
	printk(KERN_ERR DRV_NAME ": Unable to set up the MFGPT clock source\n");
	return -EIO;
}
Ejemplo n.º 10
0
static int ot200_backlight_update_status(struct backlight_device *bl)
{
	struct ot200_backlight_data *data = bl_get_data(bl);
	int brightness = bl->props.brightness;

	if (bl->props.state & BL_CORE_FBBLANK)
		brightness = 0;

	/* enable or disable PWM timer */
	if (brightness == 0)
		cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, 0);
	else if (data->current_brightness == 0) {
		cs5535_mfgpt_write(pwm_timer, MFGPT_REG_COUNTER, 0);
		cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP,
			MFGPT_SETUP_CNTEN);
	}

	/* apply new brightness value */
	cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1,
		MAX_COMP2 - dim_table[brightness]);
	data->current_brightness = brightness;

	return 0;
}
Ejemplo n.º 11
0
static void geodewdt_disable(void)
{
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0);
	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0);
}
Ejemplo n.º 12
0
static long geodewdt_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int interval;

	static const struct watchdog_info ident = {
		.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
		| WDIOF_MAGICCLOSE,
		.firmware_version =     1,
		.identity =             WATCHDOG_NAME,
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident,
				    sizeof(ident)) ? -EFAULT : 0;
		break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);

	case WDIOC_SETOPTIONS:
	{
		int options, ret = -EINVAL;

		if (get_user(options, p))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			geodewdt_disable();
			ret = 0;
		}

		if (options & WDIOS_ENABLECARD) {
			geodewdt_ping();
			ret = 0;
		}

		return ret;
	}
	case WDIOC_KEEPALIVE:
		geodewdt_ping();
		return 0;

	case WDIOC_SETTIMEOUT:
		if (get_user(interval, p))
			return -EFAULT;

		if (geodewdt_set_heartbeat(interval))
			return -EINVAL;
	/* Fall through */
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);

	default:
		return -ENOTTY;
	}

	return 0;
}

static const struct file_operations geodewdt_fops = {
	.owner          = THIS_MODULE,
	.llseek         = no_llseek,
	.write          = geodewdt_write,
	.unlocked_ioctl = geodewdt_ioctl,
	.open           = geodewdt_open,
	.release        = geodewdt_release,
};

static struct miscdevice geodewdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &geodewdt_fops,
};

static int __devinit geodewdt_probe(struct platform_device *dev)
{
	int ret;

	wdt_timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
	if (!wdt_timer) {
		pr_err("No timers were available\n");
		return -ENODEV;
	}

	/* Set up the timer */

	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_SETUP,
			  GEODEWDT_SCALE | (3 << 8));

	/* Set up comparator 2 to reset when the event fires */
	cs5535_mfgpt_toggle_event(wdt_timer, MFGPT_CMP2, MFGPT_EVENT_RESET, 1);

	/* Set up the initial timeout */

	cs5535_mfgpt_write(wdt_timer, MFGPT_REG_CMP2,
		timeout * GEODEWDT_HZ);

	ret = misc_register(&geodewdt_miscdev);

	return ret;
}

static int __devexit geodewdt_remove(struct platform_device *dev)
{
	misc_deregister(&geodewdt_miscdev);
	return 0;
}