#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
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;
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;
/* 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);
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*/
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;
* 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);
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)
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;
* 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);
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;
}
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);
}
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;
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 = {
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;
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;
}