From 8e4bff4cab0ddac6060645b0715210484d02ff40 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Wed, 30 Aug 2017 08:25:59 +0000 Subject: Initial file dump from open source release --- drivers/misc/sprd_dwnload/Kconfig | 10 + drivers/misc/sprd_dwnload/Makefile | 2 + drivers/misc/sprd_dwnload/sprd_download.c | 272 +++++++++++++++++++ drivers/misc/sprd_dwnload/sprd_power_ctl.c | 417 +++++++++++++++++++++++++++++ 4 files changed, 701 insertions(+) create mode 100644 drivers/misc/sprd_dwnload/Kconfig create mode 100644 drivers/misc/sprd_dwnload/Makefile create mode 100644 drivers/misc/sprd_dwnload/sprd_download.c create mode 100644 drivers/misc/sprd_dwnload/sprd_power_ctl.c (limited to 'drivers/misc/sprd_dwnload') diff --git a/drivers/misc/sprd_dwnload/Kconfig b/drivers/misc/sprd_dwnload/Kconfig new file mode 100644 index 00000000..7612596b --- /dev/null +++ b/drivers/misc/sprd_dwnload/Kconfig @@ -0,0 +1,10 @@ +config SPRD_DOWNLOAD_IMG + tristate "SPRD Marlin Download img" + default n + help + If you say yes here you can use the fdl and img for marlin. +config SPRD_DOWNLOAD_POWER_CTL + bool "SPRD Marlin Power control" + default n + help + If you say yes here you can use the marlin chip. diff --git a/drivers/misc/sprd_dwnload/Makefile b/drivers/misc/sprd_dwnload/Makefile new file mode 100644 index 00000000..01f2750e --- /dev/null +++ b/drivers/misc/sprd_dwnload/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_SPRD_DOWNLOAD_IMG) += sprd_download.o +obj-$(CONFIG_SPRD_DOWNLOAD_POWER_CTL) += sprd_power_ctl.o diff --git a/drivers/misc/sprd_dwnload/sprd_download.c b/drivers/misc/sprd_dwnload/sprd_download.c new file mode 100644 index 00000000..072a51cd --- /dev/null +++ b/drivers/misc/sprd_dwnload/sprd_download.c @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../sdiodev/sdio_dev.h" +#include "../mdbg/mdbg_sdio.h" + +#define DLOADER_NAME "download" + +#define DOWNLOAD_CHANNEL_READ 12 +#define DOWNLOAD_CHANNEL_WRITE 3 +#define DOWNLOAD_CALI_WRITE 0 + + +#define READ_BUFFER_SIZE (4096) +#define WRITE_BUFFER_SIZE (129*1024) + +bool flag_read = 0; +uint32 read_len; + +struct dloader_dev{ + int open_count; + atomic_t read_excl; + atomic_t write_excl; + char *read_buffer; + char *write_buffer; +}; +static struct dloader_dev *download_dev=NULL; +static struct wake_lock download_wake_lock; +static bool flag_cali = false; + +extern void set_sprd_download_fin(int dl_tag); +static inline int sprd_download_lock(atomic_t *excl) +{ + if (atomic_inc_return(excl) == 1) { + return 0; + } else { + atomic_dec(excl); + return -1; + } +} + +static inline void sprd_download_unlock(atomic_t *excl) +{ + atomic_dec(excl); +} + +void sprd_download_sdio_read(void) +{ + read_len = sdio_dev_get_chn_datalen(DOWNLOAD_CHANNEL_READ); + if(read_len <= 0){ + return; + } + + sdio_dev_read(DOWNLOAD_CHANNEL_READ,download_dev->read_buffer,&read_len); + printk(KERN_INFO "%s read: %s\n",__func__,download_dev->read_buffer); + flag_read = 1; + return; +} + +int sprd_download_sdio_write(char *buffer, uint32 size) +{ + if(true == flag_cali) + sdio_dev_write(DOWNLOAD_CALI_WRITE, buffer, size); + else + sdio_dev_write(DOWNLOAD_CHANNEL_WRITE, buffer, size); + printk_ratelimited(KERN_INFO "%s size: %d\n",__func__,size); + return size; +} + +int sprd_download_sdio_init(void) +{ + int retval=0; + + retval = sdiodev_readchn_init(DOWNLOAD_CHANNEL_READ, sprd_download_sdio_read,0); + if(retval!= 0){ + printk(KERN_ERR "Sdio dev read channel init failed!"); + retval = -1; + } + + return retval; +} + + +static int sprd_download_open(struct inode *inode,struct file *filp) +{ + if (download_dev==NULL) { + return -EIO; + } + if (download_dev->open_count!=0) { + printk(KERN_ERR "dloader_open %d \n",download_dev->open_count); + return -EBUSY; + } + + marlin_sdio_init(); + mdbg_channel_init(); + flag_read = 0; + + download_dev->open_count++; + wake_lock(&download_wake_lock); + if(sprd_download_sdio_init()< 0){ + printk(KERN_ERR "sprd_download_sdio_init failed \n"); + return -EBUSY; + } + + printk(KERN_INFO "sprd_download_open %d\n", download_dev->open_count); + return 0; +} +static int sprd_download_read(struct file *filp,char __user *buf,size_t count,loff_t *pos) +{ + if ((download_dev==NULL)||(download_dev->open_count!=1)) { + printk(KERN_ERR "%s return point 1.\n",__func__); + return -EIO; + } + + if (sprd_download_lock(&download_dev->read_excl)){ + printk(KERN_ERR "%s return point 2.\n",__func__); + return -EBUSY; + } + + if(count > READ_BUFFER_SIZE) + count = READ_BUFFER_SIZE; + + if(!flag_read){ + //printk(KERN_INFO "%s return point 3.\n",__func__); + sprd_download_unlock(&download_dev->read_excl); + return 0; + } + + if(copy_to_user(buf,download_dev->read_buffer,read_len)){ + sprd_download_unlock(&download_dev->read_excl); + return -EFAULT; + } + flag_read = 0; + sprd_download_unlock(&download_dev->read_excl); + + return read_len; +} + +static int sprd_download_write(struct file *filp, const char __user *buf,size_t count,loff_t *pos) +{ + if ((download_dev==NULL)||(download_dev->open_count!=1)) + return -EIO; + + if (sprd_download_lock(&download_dev->write_excl)) + return -EBUSY; + + if (count > WRITE_BUFFER_SIZE ) { + sprd_download_unlock(&download_dev->write_excl); + return -EINVAL; + } + + if (copy_from_user(download_dev->write_buffer,buf,count )){ + sprd_download_unlock(&download_dev->write_excl); + return -EFAULT; + } + + while(1 != get_apsdiohal_status()){ + printk("SDIO dev not ready, wait 50ms and try again!\n"); + msleep(50); + } + + if(strncmp(download_dev->write_buffer,"start_calibration",17) == 0) + { + printk("wait marlin ready start\n"); + /*wait marlin ready*/ + while(1){ + if(1 == get_sdiohal_status()){ + //marlin_sdio_sync_uninit(); + flag_cali = true; + printk("wait marlin ready ok\n"); + break; + } + msleep(50); + } + }else if(strncmp(download_dev->write_buffer,"end_calibration",15) == 0) + flag_cali = false; + else + sprd_download_sdio_write(download_dev->write_buffer,count); + + sprd_download_unlock(&download_dev->write_excl); + + return count; +} + +static int sprd_download_release(struct inode *inode,struct file *filp) +{ + printk(KERN_INFO "%s\n",__func__); + sdiodev_readchn_uninit(DOWNLOAD_CHANNEL_READ); + wake_unlock(&download_wake_lock); + download_dev->open_count--; + set_sprd_download_fin(1); + return 0; +} + +static struct file_operations sprd_download_fops = { + .owner = THIS_MODULE, + .read = sprd_download_read, + .write = sprd_download_write, + .open = sprd_download_open, + .release = sprd_download_release, +}; +static struct miscdevice sprd_download_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = DLOADER_NAME, + .fops = &sprd_download_fops, +}; +static int __init sprd_download_init(void) +{ + struct dloader_dev *dev; + int err=0; + + printk(KERN_INFO "%s\n",__func__); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->open_count = 0; + + atomic_set(&dev->read_excl, 0); + atomic_set(&dev ->write_excl, 0); + download_dev = dev; + wake_lock_init(&download_wake_lock,WAKE_LOCK_SUSPEND,"download_wake_lock"); + err = misc_register(&sprd_download_device); + + if(err){ + printk(KERN_INFO "download dev add failed!!!\n"); + kfree(dev); + } + + download_dev->read_buffer = kzalloc(READ_BUFFER_SIZE, GFP_KERNEL); + if (download_dev->read_buffer == NULL) { + printk(KERN_ERR "DLoade_open fail(NO MEM) \n"); + return -ENOMEM; + } + download_dev->write_buffer = kzalloc(WRITE_BUFFER_SIZE+4, GFP_KERNEL); + if (download_dev->write_buffer == NULL) { + kfree(download_dev->read_buffer); + download_dev->read_buffer = NULL; + printk(KERN_ERR "DLoade_open fail(NO MEM) \n"); + return -ENOMEM; + } + return err; +} +static void __exit sprd_download_cleanup(void) +{ + kfree(download_dev->read_buffer); + kfree(download_dev->write_buffer); + download_dev->read_buffer = NULL; + download_dev->write_buffer = NULL; + misc_deregister(&sprd_download_device); + kfree(download_dev); + wake_lock_destroy(&download_wake_lock); + download_dev = NULL; +} +module_init(sprd_download_init); +module_exit(sprd_download_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("sprd download img driver"); + diff --git a/drivers/misc/sprd_dwnload/sprd_power_ctl.c b/drivers/misc/sprd_dwnload/sprd_power_ctl.c new file mode 100644 index 00000000..0b34dbe6 --- /dev/null +++ b/drivers/misc/sprd_dwnload/sprd_power_ctl.c @@ -0,0 +1,417 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define POWER_CTL_NAME "power_ctl" + +#define DOWNLOAD_IOCTL_BASE 'z' +#define DOWNLOAD_POWER_ON _IO(DOWNLOAD_IOCTL_BASE, 0x01) +#define DOWNLOAD_POWER_OFF _IO(DOWNLOAD_IOCTL_BASE, 0x02) +#define DOWNLOAD_POWER_RST _IO(DOWNLOAD_IOCTL_BASE, 0x03) +#define GNSS_CHIP_EN _IO(DOWNLOAD_IOCTL_BASE, 0x04) +#define GNSS_CHIP_DIS _IO(DOWNLOAD_IOCTL_BASE, 0x05) +#define GNSS_LNA_EN _IO(DOWNLOAD_IOCTL_BASE, 0x06) +#define GNSS_LNA_DIS _IO(DOWNLOAD_IOCTL_BASE, 0x07) + +struct sprd_gnss +{ + u32 chip_en; + struct regulator *vdd_lna; +}; + +static struct sprd_gnss gnss_dev; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct early_suspend gnss_suspend; +wait_queue_head_t gnss_sleep_wait; +bool gnss_flag_sleep = false; +bool gnss_flag_resume = false; +static char gnss_status[16] = {0}; +#endif + + +static int sprd_power_ctl_open(struct inode *inode,struct file *filp) +{ + return 0; +} + +static int sprd_power_ctl_release(struct inode *inode,struct file *filp) +{ + return 0; +} + + +static void download_clk_init(bool enable) +{ + int err; + const char *clk_name; + struct device_node *np; + static struct clk *download_clk = NULL; + + np = of_find_node_by_name(NULL, "sprd-marlin"); + if (!np) { + printk(KERN_ERR"sprd-marlin not found"); + return; + } + + err = of_property_read_string(np, "clk-name", &clk_name); + if (err) { + printk(KERN_ERR"get clk-name failed"); + return; + } + + if (download_clk == NULL) { + download_clk = clk_get(NULL, clk_name); + if (IS_ERR(download_clk)) { + printk("failed to get parent %s\n", clk_name); + return; + } + clk_set_rate(download_clk, 32000); + } + + #ifdef CONFIG_OF + if (enable) { + clk_prepare_enable(download_clk); + }else{ + clk_disable_unprepare(download_clk); + } + #else + if (enable) { + clk_enable(download_clk); + }else{ + clk_disable(download_clk); + } + #endif +} + +static DEFINE_MUTEX(power_ctl_lock); +static void sprd_download_poweron(bool enable) +{ + int ret; + int gpio_dwnld; + static bool request = 0; + const char *vdd_dwnld = NULL; + static struct regulator *download_vdd = NULL; + struct device_node *np; + static unsigned int power_count = 0; + + np = of_find_node_by_name(NULL, "sprd-marlin"); + if (!np) { + printk(KERN_ERR"sprd-marlin not found"); + return; + } + + gpio_dwnld = of_get_gpio(np, 5); + if (gpio_is_valid(gpio_dwnld)) { /*gpio 1v6 power supply*/ + if(0 == request) { + ret = gpio_request (gpio_dwnld, "download"); + if (ret){ + printk ("gpio_dwnld request err: %d\n", gpio_dwnld); + } + } + else{ + request = 1; + } + + if (enable) { + gpio_direction_output(gpio_dwnld,1); + + } + else { + gpio_direction_output(gpio_dwnld,0); + } + } else { /*ldo 1v6 power supply*/ + + ret = of_property_read_string(np, "vdd-download", &vdd_dwnld); + if (ret) { + printk(KERN_ERR"get vdd-download failed"); + return; + } + + if (download_vdd == NULL) { + download_vdd = regulator_get(NULL, vdd_dwnld); + + if (IS_ERR(download_vdd)) { + printk(KERN_ERR"Get regulator of vdd-download error!\n"); + return; + } + } + #ifdef CONFIG_MACH_SHARKLS_J1MINI + gpio_request(131,"vdd_pa"); + gpio_direction_output(131,1); + gpio_set_value(131, 1); + #endif + + mutex_lock(&power_ctl_lock); + if(enable){ + if(0 == power_count){ + regulator_set_voltage(download_vdd, 1600000, 1600000); + ret = regulator_enable(download_vdd); + printk("sprd_download_poweron on\n"); + } + power_count++; + } + else { + power_count--; + if(0 == power_count) + { + if(regulator_is_enabled(download_vdd)) + ret = regulator_disable(download_vdd); + printk("sprd_download_poweron off\n"); + } + } + mutex_unlock(&power_ctl_lock); + } +} + +static void sprd_download_rst(void) +{ + int ret; + u32 gpio_rst; + static bool request = 0; + struct device_node *np; + + np = of_find_node_by_name(NULL, "sprd-marlin"); + if (!np) { + printk(KERN_ERR"sprd-marlin not found"); + return; + } + gpio_rst = of_get_gpio(np, 4); + if(0 == request) + { + ret = gpio_request (gpio_rst, "download"); + if (ret){ + printk (KERN_ERR"gpio_rst request err: %d\n", gpio_rst); + } + else{ + request = 1; + } + } + gpio_direction_output(gpio_rst,1); + msleep(1); + gpio_direction_output(gpio_rst,0); + msleep(1); + gpio_direction_output(gpio_rst,1); + msleep(1); +} + +static void sprd_gnss_chip_en(bool enable) +{ + if(enable) { + gpio_direction_output(gnss_dev.chip_en,0); + msleep(1); + gpio_direction_output(gnss_dev.chip_en,1); + msleep(1); + }else { + gpio_direction_output(gnss_dev.chip_en,0); + } +} + +static void gnss_lna_enable(bool on) +{ + int ret; + + if(gnss_dev.vdd_lna != NULL){ + if (on){ + regulator_set_voltage(gnss_dev.vdd_lna, 2800000, 2800000); + ret = regulator_enable(gnss_dev.vdd_lna); + }else if(regulator_is_enabled(gnss_dev.vdd_lna)) { + ret = regulator_disable(gnss_dev.vdd_lna); + } + } +} + +static long sprd_power_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + printk("DOWNLOAD IOCTL: 0x%x.\n", cmd); + + switch (cmd) { + case DOWNLOAD_POWER_ON: + sprd_download_poweron(1); + download_clk_init(1); + break; + case DOWNLOAD_POWER_OFF: + sprd_download_poweron(0); + break; + case DOWNLOAD_POWER_RST: + sprd_download_rst(); + break; + case GNSS_CHIP_EN: + sprd_gnss_chip_en(1); + gnss_lna_enable(1); + break; + case GNSS_CHIP_DIS: + sprd_gnss_chip_en(0); + break; + case GNSS_LNA_EN: + gnss_lna_enable(1); + break; + case GNSS_LNA_DIS: + gnss_lna_enable(0); + break; + } + return 0; +} + +static void sprd_download_dts_init(void) +{ + int ret; + struct device_node *np; + const char *vdd_lna = NULL; + + np = of_find_node_by_name(NULL, "sprd-ge2"); + if (!np) { + printk(KERN_ERR"sprd-gnss not found"); + return; + } + + ret = of_property_read_string(np, "vdd-lna", &vdd_lna); + if (ret){ + printk(KERN_ERR"get vdd-lna failed"); + return; + } + + gnss_dev.vdd_lna = regulator_get(NULL, vdd_lna); + if (IS_ERR(gnss_dev.vdd_lna)){ + printk(KERN_ERR"Get regulator of vdd-lna error!\n"); + return; + } + + gnss_dev.chip_en = of_get_gpio(np, 0); + ret = gpio_request (gnss_dev.chip_en, "ge2_chip_en"); + if (ret){ + printk (KERN_ERR"gnss_dev.chip_en request err: %d\n", gnss_dev.chip_en); + } +} + + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void gnss_early_suspend(struct early_suspend *handler) +{ + printk("%s\n",__func__); + gnss_flag_sleep = true; + gnss_flag_resume = false; +} + +static void gnss_late_resume(struct early_suspend *handler) +{ + printk("%s\n",__func__); + gnss_flag_resume = true; + gnss_flag_sleep = false; +} + +static unsigned int gnss_poll(struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + + poll_wait(filp, &gnss_sleep_wait, wait); + if(gnss_flag_sleep) + { + printk("%s gnss_flag_sleep:%d\n",__func__,gnss_flag_sleep); + gnss_flag_sleep = false; + memcpy(gnss_status,"gnss_sleep ",11); + mask |= POLLIN | POLLRDNORM; + } + + if(gnss_flag_resume) + { + printk("%s gnss_flag_resume:%d\n",__func__,gnss_flag_resume); + gnss_flag_resume = false; + memcpy(gnss_status,"gnss_resume",11); + mask |= POLLIN | POLLRDNORM; + } + + return mask; +} + +static int sprd_gnss_read(struct file *filp,char __user *buf,size_t count,loff_t *pos) +{ + if(count < 11) + return -EINVAL; + + if(count > 11) + count = 11; + + if(copy_to_user(buf,gnss_status,count)){ + return -EFAULT; + } + + return count; +} +#endif + +static struct file_operations sprd_power_ctl__fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = sprd_power_ctl_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = sprd_power_ctl_ioctl, + #endif + .open = sprd_power_ctl_open, + .release = sprd_power_ctl_release, + #ifdef CONFIG_HAS_EARLYSUSPEND + .read = sprd_gnss_read, + .poll = gnss_poll, + #endif +}; + +static struct miscdevice sprd_power_ctl_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = POWER_CTL_NAME, + .fops = &sprd_power_ctl__fops, +}; + +static int __init sprd_power_ctl_init(void) +{ + int err=0; + printk("sprd_power_ctl_init\n"); + err = misc_register(&sprd_power_ctl_device); + + if(err){ + printk(KERN_INFO "download power control dev add failed!!!\n"); + } + + sprd_download_dts_init(); + + #ifdef CONFIG_HAS_EARLYSUSPEND + gnss_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING + 30; + gnss_suspend.suspend = gnss_early_suspend; + gnss_suspend.resume = gnss_late_resume; + register_early_suspend(&gnss_suspend); + + init_waitqueue_head(&gnss_sleep_wait); + #endif + return err; +} + +static void __exit sprd_power_ctl_cleanup(void) +{ + misc_deregister(&sprd_power_ctl_device); +} +module_init(sprd_power_ctl_init); +module_exit(sprd_power_ctl_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("sprd download img driver"); + -- cgit v1.3.1