rk: ion: assign sg's dma_length in ion allocation if CONFIG_NEED_SG_DMA_LENGTH is set
[firefly-linux-kernel-4.4.55.git] / drivers / pwm / pwm-rockchip.c
old mode 100644 (file)
new mode 100755 (executable)
index 6ac796b..288f1b4
@@ -81,20 +81,12 @@ module_param_named(dbg_level, pwm_dbg_level, int, 0644);
 #define PWMCR_MIN_PRESCALE     0x00
 #define PWMCR_MAX_PRESCALE     0x07
 
-#define PWMDCR_MIN_DUTY                0x0001
+#define PWMDCR_MIN_DUTY                0x0000
 #define PWMDCR_MAX_DUTY                0xFFFF
 
 #define PWMPCR_MIN_PERIOD              0x0001
 #define PWMPCR_MAX_PERIOD              0xFFFF
-#if 0
-static spinlock_t pwm_lock[4] = {
-        __SPIN_LOCK_UNLOCKED(pwm_lock0),
-        __SPIN_LOCK_UNLOCKED(pwm_lock1),
-        __SPIN_LOCK_UNLOCKED(pwm_lock2),
-        __SPIN_LOCK_UNLOCKED(pwm_lock3),
-};
-#endif
-int spinlock_num = 0;
+
 /********************************************
  * struct rk_pwm_chip - struct representing pwm chip
 
@@ -105,6 +97,8 @@ int spinlock_num = 0;
  struct rk_pwm_chip {
        void __iomem *base;
        struct clk *clk;
+       struct clk *aclk_lcdc;
+       struct clk *hclk_lcdc;
        struct pwm_chip chip;
        unsigned int pwm_id;
        spinlock_t              lock;
@@ -145,7 +139,6 @@ static int  rk_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm,
        struct rk_pwm_chip *pc = to_rk_pwm_chip(chip);
        u64 val, div, clk_rate;
        unsigned long prescale = PWMCR_MIN_PRESCALE, pv, dc;
-       int ret;
        u32 off, on;
        int conf=0;
        unsigned long flags;
@@ -195,21 +188,16 @@ static int  rk_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm,
 
        /* NOTE: the clock to PWM has to be enabled first before writing to the registers. */
 
-#if PWM_CLK
-       ret = clk_enable(pc->clk);
-       if (ret)
-               return ret;
-#endif
         spin_lock_irqsave(lock, flags);
 
        conf |= (prescale << DW_PWM_PRESCALE);
        barrier();
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CTRL,off);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_HRC,dc);//0x1900);// dc);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_LRC, pv);//0x5dc0);//pv);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CNTR,0);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CTRL,on|conf);
        
        spin_unlock_irqrestore(lock, flags);    
@@ -243,11 +231,11 @@ static void rk_pwm_resume_v1(struct pwm_chip *chip, struct pwm_device *pwm)
        int     off =  PWM_RESET;
 
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CTRL,off);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_HRC,pc->pwm_duty);//0x1900);// dc);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_LRC, pc->pwm_period);//0x5dc0);//pv);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CNTR,pc->pwm_count);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CTRL,pc->pwm_ctrl);
 }
 /* config for rockchip,pwm*/
@@ -257,7 +245,6 @@ static int  rk_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm,
        struct rk_pwm_chip *pc = to_rk_pwm_chip(chip);
        u64 val, div, clk_rate;
        unsigned long prescale = PWMCR_MIN_PRESCALE, pv, dc;
-       int ret;
        u32  on;
        int conf=0;
        unsigned long flags;
@@ -310,20 +297,16 @@ static int  rk_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm,
         * NOTE: the clock to PWM has to be enabled first before writing to the
         * registers.
         */
-
-       ret = clk_enable(pc->clk);
-       if (ret)
-               return ret;
         spin_lock_irqsave(lock, flags);
 
        conf |= (prescale << RK_PWM_PRESCALE);  
        barrier();
        //rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CTRL,off);
-       //dsb();
+       //dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_DUTY,dc);//0x1900);// dc);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_PERIOD,pv);//0x5dc0);//pv);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CNTR,0);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CTRL,on|conf);
        spin_unlock_irqrestore(lock, flags);    
 
@@ -361,11 +344,10 @@ static void rk_pwm_resume_v2(struct pwm_chip *chip, struct pwm_device *pwm)
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_DUTY,    pc->pwm_duty);//0x1900);// dc);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_PERIOD, pc->pwm_period);//0x5dc0);//pv);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CNTR,pc->pwm_count);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_CTRL,pc->pwm_ctrl);
 }
-//#define grf_readl(offset)    readl_relaxed(RK_GRF_VIRT + offset)
-//#define grf_writel(v, offset)        do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
+
 /* config for rockchip,pwm*/
 static int  rk_pwm_config_v3(struct pwm_chip *chip, struct pwm_device *pwm,
                            int duty_ns, int period_ns)
@@ -373,7 +355,6 @@ static int  rk_pwm_config_v3(struct pwm_chip *chip, struct pwm_device *pwm,
        struct rk_pwm_chip *pc = to_rk_pwm_chip(chip);
        u64 val, div, clk_rate;
        unsigned long prescale = PWMCR_MIN_PRESCALE, pv, dc;
-       int  ret;
        u32 on;
        int conf=0;
        unsigned long flags;
@@ -426,10 +407,11 @@ static int  rk_pwm_config_v3(struct pwm_chip *chip, struct pwm_device *pwm,
         * NOTE: the clock to PWM has to be enabled first before writing to the
         * registers.
         */
-
+#if 0
        ret = clk_enable(pc->clk);
        if (ret)
                return ret;
+#endif
         spin_lock_irqsave(lock, flags);
 
        conf |= (prescale << RK_PWM_PRESCALE);
@@ -437,21 +419,14 @@ static int  rk_pwm_config_v3(struct pwm_chip *chip, struct pwm_device *pwm,
        barrier();
 //     rk_pwm_writel(pc, pwm->hwpwm, VOP_REG_CTRL,off);
        
-//     dsb();
+//     dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_DUTY,dc);   //   2    0x1900);// dc);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_PERIOD,pv);   // 4 0x5dc0);//pv);
        rk_pwm_writel(pc, pwm->hwpwm, VOP_REG_CNTR,0);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, VOP_REG_CTRL,on|conf);
-#if 0
-       //grf_writel(0x00030002,0x6c);
-       DBG("VOP  iomux 0x%x\n", grf_readl(0x6c));
-       DBG("VOP_REG_CTRL0x%x\n", rk_pwm_readl(pc, pwm->hwpwm, VOP_REG_CTRL));
-       DBG("PWM_REG_DUTY0x%x\n", rk_pwm_readl(pc, pwm->hwpwm, PWM_REG_DUTY));
-       DBG("PWM_REG_PERIOD 0x%x\n", rk_pwm_readl(pc, pwm->hwpwm, PWM_REG_PERIOD));
-       DBG("VOP_REG_CNTR 0x%x\n", rk_pwm_readl(pc, pwm->hwpwm, VOP_REG_CNTR));
-#endif
-        spin_unlock_irqrestore(lock, flags);   
+
+       spin_unlock_irqrestore(lock, flags);    
 
        return 0;
 }
@@ -483,7 +458,7 @@ static void rk_pwm_resume_v3(struct pwm_chip *chip, struct pwm_device *pwm)
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_DUTY,    pc->pwm_duty);//0x1900);// dc);
        rk_pwm_writel(pc, pwm->hwpwm, PWM_REG_PERIOD, pc->pwm_period);//0x5dc0);//pv);
        rk_pwm_writel(pc, pwm->hwpwm, VOP_REG_CNTR,pc->pwm_count);
-       dsb();
+       dsb(sy);
        rk_pwm_writel(pc, pwm->hwpwm, VOP_REG_CTRL,pc->pwm_ctrl);
 }
 
@@ -494,18 +469,51 @@ static int  rk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        struct rk_pwm_chip *pc = to_rk_pwm_chip(chip);
        int ret;
        
+       ret = clk_enable(pc->clk);
+       if (ret)
+               return ret;
+
+       if (pc->aclk_lcdc) {
+               ret = clk_enable(pc->aclk_lcdc);
+               if (ret)
+                       return ret;
+       }
+       if (pc->hclk_lcdc) {
+               ret = clk_enable(pc->hclk_lcdc);
+               if (ret)
+                       return ret;
+       }
+
        ret = pc->config(chip, pwm, duty_ns, period_ns);
 
+       if (pc->aclk_lcdc)
+               clk_disable(pc->aclk_lcdc);
+       if (pc->hclk_lcdc)
+               clk_disable(pc->hclk_lcdc);
+
+       clk_disable(pc->clk);
+
        return 0;
 }
 static int rk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct rk_pwm_chip *pc = to_rk_pwm_chip(chip);
-       int rc = 0;
+       int ret = 0;
 
-       rc = clk_enable(pc->clk);
-       if (rc)
-               return rc;
+       ret = clk_enable(pc->clk);
+       if (ret)
+               return ret;
+
+       if (pc->aclk_lcdc) {
+               ret = clk_enable(pc->aclk_lcdc);
+               if (ret)
+                       return ret;
+       }
+       if (pc->hclk_lcdc) {
+               ret = clk_enable(pc->hclk_lcdc);
+               if (ret)
+                       return ret;
+       }
 
        pc->set_enable(chip, pwm,true);
        return 0;
@@ -516,7 +524,14 @@ static void rk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
        struct rk_pwm_chip *pc = to_rk_pwm_chip(chip);
 
        pc->set_enable(chip, pwm,false);
+
+       if (pc->aclk_lcdc)
+               clk_disable(pc->aclk_lcdc);
+       if (pc->hclk_lcdc)
+               clk_disable(pc->hclk_lcdc);
+
        clk_disable(pc->clk);
+
 }
 
 static const struct pwm_ops rk_pwm_ops = {
@@ -585,25 +600,33 @@ static int rk_pwm_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to allocate memory\n");
                return -ENOMEM;
        }
-#if 0
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "no memory resources defined\n");
-               return -ENODEV;
-       }
-       pc->base = devm_ioremap_resource(&pdev->dev, r);
-       if (IS_ERR(pc->base))
-               return PTR_ERR(pc->base);
-#endif
+
        pc->base = of_iomap(np, 0);
-       if (IS_ERR(pc->base)){
+       if (IS_ERR(pc->base)) {
                printk("PWM base ERR \n");
                return PTR_ERR(pc->base);
        }
-       pc->clk = devm_clk_get(&pdev->dev,"pclk_pwm");
+       pc->clk = devm_clk_get(&pdev->dev, "pclk_pwm");
        if (IS_ERR(pc->clk))
                return PTR_ERR(pc->clk);
 
+       if (of_device_is_compatible(np, "rockchip,vop-pwm")) {
+               pc->aclk_lcdc = devm_clk_get(&pdev->dev, "aclk_lcdc");
+               if (IS_ERR(pc->aclk_lcdc))
+                       return PTR_ERR(pc->aclk_lcdc);
+
+               pc->hclk_lcdc = devm_clk_get(&pdev->dev, "hclk_lcdc");
+               if (IS_ERR(pc->hclk_lcdc))
+                       return PTR_ERR(pc->hclk_lcdc);
+
+               ret = clk_prepare(pc->aclk_lcdc);
+               if (ret)
+                       return ret;
+               clk_prepare(pc->hclk_lcdc);
+               if (ret)
+                       return ret;
+       }
+
        platform_set_drvdata(pdev, pc);
        data = of_id->data;
        pc->config = data->config;
@@ -614,27 +637,21 @@ static int rk_pwm_probe(struct platform_device *pdev)
        pc->chip.ops = &rk_pwm_ops;  
        pc->chip.base = -1;
        pc->chip.npwm = NUM_PWM;
-       pc->lock = __SPIN_LOCK_UNLOCKED(PWM##spinlock_num);
-       spinlock_num ++;
-#if PWM_CLK
+       spin_lock_init(&pc->lock);
        ret = clk_prepare(pc->clk);
        if (ret)
                return ret;
-#endif
 
-       ret = clk_enable(pc->clk);
-       if (ret) {
-               clk_unprepare(pc->clk);
-               return ret;
-       }
-       /* Following enables PWM chip, channels would still be enabled individually through their control register */
-       DBG("npwm = %d, of_pwm_ncells =%d \n", pc->chip.npwm,pc->chip.of_pwm_n_cells);
+       /* Following enables PWM chip, channels would still
+       be enabled individually through their control register */
+       DBG("npwm = %d, of_pwm_ncells =%d \n"
+               , pc->chip.npwm, pc->chip.of_pwm_n_cells);
        ret = pwmchip_add(&pc->chip);
-       if (ret < 0) {
-               clk_unprepare(pc->clk);
-               dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+       if (ret < 0){
+               printk("failed to add pwm\n");
+               return ret;
        }
-       
+
        DBG("%s end \n",__FUNCTION__);
        return ret;
 }