UPSTREAM: ARM: 8478/2: arm/arm64: add arm-smccc
[firefly-linux-kernel-4.4.55.git] / drivers / mfd / rk610-core.c
index 88054431828adc67bbc634706881ae0ccad1f21c..b0a6a9ba7ebf64b6311450430165f79a61ee3eea 100755 (executable)
@@ -4,20 +4,25 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <asm/gpio.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/rk610_core.h>
 #include <linux/clk.h>
-#include <mach/iomux.h>
+#include <linux/gpio.h>
 #include <linux/err.h>
 #include <linux/slab.h>
-
-#if defined(CONFIG_ARCH_RK3066B)
-#define RK610_RESET_PIN   RK30_PIN2_PC5
-#elif defined(CONFIG_ARCH_RK30)
-#define RK610_RESET_PIN   RK30_PIN0_PC6
-#else
-#define RK610_RESET_PIN   RK29_PIN6_PC1
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+#if defined(CONFIG_DEBUG_FS)
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
 #endif
 
+#define GPIO_HIGH 1
+#define GPIO_LOW 0
+
 /*
  * Debug
  */
 #endif
 
 static struct i2c_client *rk610_control_client = NULL;
-#ifdef CONFIG_RK610_LVDS
-extern int rk610_lcd_init(struct rk610_core_info *rk610_core_info);
-#else
-int rk610_lcd_init(struct rk610_core_info *rk610_core_info){}
-#endif
+
+int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
+{
+       struct i2c_adapter *adap=client->adapter;
+       struct i2c_msg msg;
+       int ret;
+       char *tx_buf = (char *)kmalloc(count + 1, GFP_KERNEL);
+       if(!tx_buf)
+               return -ENOMEM;
+       tx_buf[0] = reg;
+       memcpy(tx_buf+1, buf, count); 
+
+       msg.addr = client->addr;
+       msg.flags = client->flags;
+       msg.len = count + 1;
+       msg.buf = (char *)tx_buf;
+       msg.scl_rate = scl_rate;
+//     msg.udelay = client->udelay;
+
+       ret = i2c_transfer(adap, &msg, 1);
+       kfree(tx_buf);
+       return (ret == 1) ? count : ret;
+
+}
+
+int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
+{
+       struct i2c_adapter *adap=client->adapter;
+       struct i2c_msg msgs[2];
+       int ret;
+       char reg_buf = reg;
+       
+       msgs[0].addr = client->addr;
+       msgs[0].flags = client->flags;
+       msgs[0].len = 1;
+       msgs[0].buf = &reg_buf;
+       msgs[0].scl_rate = scl_rate;
+//     msgs[0].udelay = client->udelay;
+
+       msgs[1].addr = client->addr;
+       msgs[1].flags = client->flags | I2C_M_RD;
+       msgs[1].len = count;
+       msgs[1].buf = (char *)buf;
+       msgs[1].scl_rate = scl_rate;
+//     msgs[1].udelay = client->udelay;
+
+       ret = i2c_transfer(adap, msgs, 2);
+
+       return (ret == 2)? count : ret;
+}
+
+
+static struct mfd_cell rk610_devs[] = {
+       {
+               .name = "rk610-lcd",
+               .id = 0,
+       },
+};
+
 int rk610_control_send_byte(const char reg, const char data)
 {
        int ret;
@@ -157,7 +216,7 @@ void rk610_control_init_codec(void)
     DBG("[%s] RK610_CONTROL_REG_CLOCK_CON1 is %x\n", __FUNCTION__, data);
 }
 #endif
-#ifdef RK610_DEBUG
+
 static int rk610_read_p0_reg(struct i2c_client *client, char reg, char *val)
 {
        return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
@@ -167,43 +226,58 @@ static int rk610_write_p0_reg(struct i2c_client *client, char reg, char *val)
 {
        return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
 }
-static ssize_t rk610_show_reg_attrs(struct device *dev,
-                                             struct device_attribute *attr,
-                                             char *buf)
-{
 
-       int i,size=0;
-       char val;
-       struct i2c_client *client=rk610_control_client;
 
-       for(i=0;i<256;i++)
+#if defined(CONFIG_DEBUG_FS)
+static int rk610_reg_show(struct seq_file *s, void *v)
+{
+       char reg = 0;
+       u8 val = 0;
+       struct rk610_core_info *core_info = s->private;
+       if(!core_info)
+       {
+               dev_err(core_info->dev,"no mfd rk610!\n");
+               return 0;
+       }
+
+       for(reg=C_PLL_CON0;reg<= I2C_CON;reg++)
        {
-               rk610_read_p0_reg(client, i,  &val);
-               if(i%16==0)
-                       size += sprintf(buf+size,"\n>>>rk610_ctl %x:",i);
-               size += sprintf(buf+size," %2x",val);
+               rk610_read_p0_reg(core_info->client, reg,  &val);
+               if(reg%8==0)
+                       seq_printf(s,"\n0x%02x:",reg);
+               seq_printf(s," %02x",val);
        }
+       seq_printf(s,"\n");
 
-       return size;
+       return 0;
+}
+
+static ssize_t rk610_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{ 
+       struct rk610_core_info *core_info = file->f_path.dentry->d_inode->i_private;
+       u32 reg,val;
+       
+       char kbuf[25];
+       if (copy_from_user(kbuf, buf, count))
+               return -EFAULT;
+       sscanf(kbuf, "%x%x", &reg,&val);
+       rk610_write_p0_reg(core_info->client, reg,  (u8*)&val);
+       return count;
 }
-static ssize_t rk610_store_reg_attrs(struct device *dev,
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t size)
+
+static int rk610_reg_open(struct inode *inode, struct file *file)
 {
-       struct i2c_client *client=NULL;
-       static char val=0,reg=0;
-       client = rk610_control_client;
-       DBG("/**********rk610 reg config******/");
-
-       sscanf(buf, "%x%x", &val,&reg);
-       DBG("reg=%x val=%x\n",reg,val);
-       rk610_write_p0_reg(client, reg,  &val);
-       DBG("val=%x\n",val);
-       return size;
+       struct rk610_core_info *core_info = inode->i_private;
+       return single_open(file,rk610_reg_show,core_info);
 }
 
-static struct device_attribute rk610_attrs[] = {
-       __ATTR(reg_ctl, 0777,rk610_show_reg_attrs,rk610_store_reg_attrs),
+static const struct file_operations rk610_reg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = rk610_reg_open,
+       .read           = seq_read,
+       .write          = rk610_reg_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
 };
 #endif
 
@@ -211,9 +285,9 @@ static int rk610_control_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        int ret;
-       struct clk *iis_clk;
        struct rk610_core_info *core_info = NULL; 
-       struct rk610_ctl_platform_data *pdata = client->dev.platform_data;
+       struct device_node *rk610_np;
+
        DBG("[%s] start\n", __FUNCTION__);
        core_info = kmalloc(sizeof(struct rk610_core_info), GFP_KERNEL);
        if(!core_info)
@@ -222,40 +296,53 @@ static int rk610_control_probe(struct i2c_client *client,
                return -ENOMEM;
        }
        memset(core_info, 0, sizeof(struct rk610_core_info));
-       core_info->pdata = pdata;
-       #if defined(CONFIG_SND_RK29_SOC_I2S_8CH)        
-       iis_clk = clk_get_sys("rk29_i2s.0", "i2s");
-       #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH)
-       iis_clk = clk_get_sys("rk29_i2s.1", "i2s");
-       #else
-       iis_clk = clk_get_sys("rk29_i2s.2", "i2s");
-       #endif
-       if (IS_ERR(iis_clk)) {
-               printk("failed to get i2s clk\n");
-               ret = PTR_ERR(iis_clk);
-       }else{
-               DBG("got i2s clk ok!\n");
-               clk_enable(iis_clk);
-               clk_set_rate(iis_clk, 11289600);
-               #if defined(CONFIG_ARCH_RK29)
-               rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
-               #elif defined(CONFIG_ARCH_RK3066B)
-               rk30_mux_api_set(GPIO1C0_I2SCLK_NAME, GPIO1C_I2SCLK);
-               #elif defined(CONFIG_ARCH_RK30)
-                rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK);
-               #endif
-               clk_put(iis_clk);
-       }
 
        rk610_control_client = client;
-       msleep(100);
-       if(core_info->pdata->rk610_power_on_init)
-               core_info->pdata->rk610_power_on_init();
+       
        core_info->client = client;
-       rk610_lcd_init(core_info);
-#ifdef RK610_DEBUG
-       device_create_file(&(client->dev), &rk610_attrs[0]);
+       core_info->dev = &client->dev;
+       i2c_set_clientdata(client,core_info);
+       
+       rk610_np = core_info->dev->of_node;
+       core_info->reset_gpio = of_get_named_gpio(rk610_np,"rk610-reset-io", 0);
+       if (!gpio_is_valid(core_info->reset_gpio)){
+               printk("invalid core_info->reset_gpio: %d\n",core_info->reset_gpio);
+               return -1;
+       }
+       ret = gpio_request(core_info->reset_gpio, "rk610-reset-io");
+       if( ret != 0){
+               printk("gpio_request core_info->reset_gpio invalid: %d\n",core_info->reset_gpio);
+               return ret;
+       }
+       gpio_direction_output(core_info->reset_gpio, GPIO_HIGH);
+       msleep(100);
+       gpio_direction_output(core_info->reset_gpio, GPIO_LOW);
+       msleep(100);
+       gpio_set_value(core_info->reset_gpio, GPIO_HIGH);
+
+       core_info->i2s_clk= clk_get(&client->dev, "i2s_clk");
+       if (IS_ERR(core_info->i2s_clk)) {
+               dev_err(&client->dev, "Can't retrieve i2s clock\n");
+               ret = PTR_ERR(core_info->i2s_clk);
+               return ret;
+       }
+       clk_set_rate(core_info->i2s_clk, 11289600);
+       clk_prepare_enable(core_info->i2s_clk);
+
+       ret = mfd_add_devices(&client->dev, -1,
+                                     rk610_devs, ARRAY_SIZE(rk610_devs),
+                                     NULL,0,NULL);
+       
+#if defined(CONFIG_DEBUG_FS)
+       core_info->debugfs_dir = debugfs_create_dir("rk610", NULL);
+       if (IS_ERR(core_info->debugfs_dir))
+       {
+               dev_err(&client->dev,"failed to create debugfs dir for rk610!\n");
+       }
+       else
+               debugfs_create_file("core", S_IRUSR,core_info->debugfs_dir,core_info,&rk610_reg_fops);
 #endif
+
     return 0;
 }
 
@@ -281,7 +368,6 @@ static struct i2c_driver rk610_control_driver = {
 
 static int __init rk610_control_init(void)
 {
-       DBG("[%s] start\n", __FUNCTION__);
        return i2c_add_driver(&rk610_control_driver);
 }
 
@@ -291,7 +377,6 @@ static void __exit rk610_control_exit(void)
 }
 
 subsys_initcall_sync(rk610_control_init);
-//module_init(rk610_control_init);
 module_exit(rk610_control_exit);