193 lines
4.4 KiB
C
193 lines
4.4 KiB
C
/*
|
|
* GSC3280 GW-JZQ GPRS Driver
|
|
*
|
|
* Copyright (C) 2013 BLX IC Design Corp.,Ltd.
|
|
* Author: Fei Lu, Lufei@china-cpu.com
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/module.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/init.h>
|
|
#include <linux/err.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/io.h>
|
|
#include <linux/of.h>
|
|
#include <linux/completion.h>
|
|
#include <asm/io.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/fcntl.h>
|
|
#include <asm/uaccess.h>
|
|
#include <linux/gpio.h>
|
|
#include <gsc3280/gpio.h>
|
|
enum {
|
|
GPRS_VCCON = 0,
|
|
GPRS_VCCOFF,
|
|
GPRS_POWERON,
|
|
GPRS_POWEROFF,
|
|
GPRS_RESET,
|
|
GPRS_PCTRLON,
|
|
GPRS_PCTRLOFF,
|
|
GPRS_GET_STATUS,
|
|
};
|
|
enum {
|
|
VCC = 0,
|
|
POWER,
|
|
PCTRL,
|
|
/*
|
|
RESET,
|
|
S0,
|
|
S1,
|
|
S2,
|
|
S3,
|
|
S4,
|
|
*/ MAX_PIN_NR,
|
|
};
|
|
struct gpio gprs_gpios[MAX_PIN_NR] = {
|
|
{GSC3280_GPC(20), GPIOF_OUT_INIT_LOW, "GPRS VCC ON/OFF"},
|
|
{GSC3280_GPB(26), GPIOF_OUT_INIT_HIGH, "GPRS POWER ON/OFF"},
|
|
{GSC3280_GPB(27), GPIOF_OUT_INIT_LOW, "GPRS PCTRL ON/OFF"},
|
|
/* {GSC3280_GPA(3), GPIOF_OUT_INIT_HIGH, "GPRS RESET"},
|
|
{GSC3280_GPA(4), GPIOF_IN, "GPRS S0"},
|
|
{GSC3280_GPA(5), GPIOF_IN, "GPRS S1"},
|
|
{GSC3280_GPB(20), GPIOF_IN, "GPRS S2"},
|
|
{GSC3280_GPB(21), GPIOF_IN, "GPRS S3"},
|
|
{GSC3280_GPA(17), GPIOF_IN, "GPRS S4"}
|
|
*/
|
|
};
|
|
struct jzq_gprs {
|
|
struct cdev cdev;
|
|
struct class *gprs_class;
|
|
dev_t dev;
|
|
};
|
|
|
|
struct jzq_gprs jzq_gprs_priv;
|
|
|
|
static long gprs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
{
|
|
|
|
switch(cmd) {
|
|
case GPRS_VCCON:
|
|
gpio_set_value(gprs_gpios[VCC].gpio, 1);
|
|
break;
|
|
case GPRS_VCCOFF:
|
|
gpio_set_value(gprs_gpios[VCC].gpio, 0);
|
|
break;
|
|
case GPRS_POWERON:
|
|
gpio_set_value(gprs_gpios[POWER].gpio, 0);
|
|
msleep(1000);
|
|
gpio_set_value(gprs_gpios[POWER].gpio, 1);
|
|
break;
|
|
case GPRS_POWEROFF:
|
|
gpio_set_value(gprs_gpios[POWER].gpio, 0);
|
|
msleep(3000);
|
|
gpio_set_value(gprs_gpios[POWER].gpio, 1);
|
|
break;
|
|
case GPRS_PCTRLON:
|
|
gpio_set_value(gprs_gpios[PCTRL].gpio, 1);
|
|
break;
|
|
case GPRS_PCTRLOFF:
|
|
gpio_set_value(gprs_gpios[PCTRL].gpio, 0);
|
|
break;
|
|
case GPRS_RESET:
|
|
/*
|
|
gpio_set_value(gprs_gpios[RESET].gpio, 0);
|
|
msleep(200);
|
|
gpio_set_value(gprs_gpios[RESET].gpio, 1);
|
|
*/
|
|
break;
|
|
case GPRS_GET_STATUS:
|
|
//gpio_set_value(gprs_gpios[S0].gpio);
|
|
break;
|
|
default:
|
|
return -ENOTTY;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gprs_open(struct inode *inode, struct file *filp)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int gprs_release(struct inode *inode, struct file *filp)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
struct file_operations gprs_fops = {
|
|
.owner = THIS_MODULE,
|
|
.unlocked_ioctl = gprs_ioctl,
|
|
.open = gprs_open,
|
|
.release = gprs_release,
|
|
};
|
|
static int __init jzq_gprs_init(void)
|
|
{
|
|
int err,ret;
|
|
int result;
|
|
int major;
|
|
|
|
result = alloc_chrdev_region(&jzq_gprs_priv.dev, 0, 0, "gprs");
|
|
major = MAJOR(jzq_gprs_priv.dev);
|
|
if (result < 0) {
|
|
printk(KERN_WARNING "jzq_gprs: can't get major %d\n", major);
|
|
return result;
|
|
}
|
|
|
|
cdev_init(&jzq_gprs_priv.cdev, &gprs_fops);
|
|
jzq_gprs_priv.cdev.owner = THIS_MODULE;
|
|
jzq_gprs_priv.cdev.ops = &gprs_fops;
|
|
|
|
err = cdev_add(&jzq_gprs_priv.cdev, jzq_gprs_priv.dev, 1);
|
|
if (err) {
|
|
printk(KERN_NOTICE "Error[%d] cdev_add .\n", err);
|
|
return -1;
|
|
}
|
|
|
|
jzq_gprs_priv.gprs_class = class_create(THIS_MODULE, "gprs");
|
|
if (IS_ERR(jzq_gprs_priv.gprs_class)) {
|
|
printk(KERN_ERR "Failed in create gprs_cdev class\n");
|
|
return -1;
|
|
}
|
|
|
|
device_create(jzq_gprs_priv.gprs_class, NULL, jzq_gprs_priv.dev, NULL, "gprs");
|
|
|
|
ret = gpio_request_array(gprs_gpios, MAX_PIN_NR);
|
|
if (ret < 0)
|
|
return ret;
|
|
return 0;
|
|
}
|
|
|
|
static void __exit jzq_gprs_exit(void)
|
|
{
|
|
gpio_free_array(gprs_gpios, MAX_PIN_NR);
|
|
cdev_del(&jzq_gprs_priv.cdev);
|
|
unregister_chrdev_region(jzq_gprs_priv.dev, 1);
|
|
device_destroy(jzq_gprs_priv.gprs_class, jzq_gprs_priv.dev);
|
|
class_destroy(jzq_gprs_priv.gprs_class);
|
|
}
|
|
|
|
|
|
module_init(jzq_gprs_init);
|
|
module_exit(jzq_gprs_exit);
|
|
|
|
|
|
MODULE_AUTHOR("lufei@china-cpu.com");
|
|
MODULE_DESCRIPTION("GSC3280 GW-JZQ GPRS Driver");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
|