111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa/* 211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Copyright (c) 2007 Ben Dooks 311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Copyright (c) 2008 Simtec Electronics 411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> 511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com> 611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * 711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * PWM driver for Samsung SoCs 811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * 911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * This program is free software; you can redistribute it and/or modify 1011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * it under the terms of the GNU General Public License as published by 1111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * the Free Software Foundation; either version 2 of the License. 1211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 1311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 1411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/bitops.h> 1511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/clk.h> 1611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/export.h> 1711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/err.h> 1811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/io.h> 1911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/kernel.h> 2011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/module.h> 21c3bdfe1f1e4e1e195945c55a2256eba89334d36cSachin Kamat#include <linux/of.h> 2211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/platform_device.h> 2311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/pwm.h> 2411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/slab.h> 2511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/spinlock.h> 2611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <linux/time.h> 2711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 2811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa/* For struct samsung_timer_variant and samsung_pwm_lock. */ 2911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#include <clocksource/samsung_pwm.h> 3011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 3111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define REG_TCFG0 0x00 3211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define REG_TCFG1 0x04 3311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define REG_TCON 0x08 3411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 3511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define REG_TCNTB(chan) (0x0c + ((chan) * 0xc)) 3611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define REG_TCMPB(chan) (0x10 + ((chan) * 0xc)) 3711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 3811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCFG0_PRESCALER_MASK 0xff 3911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCFG0_PRESCALER1_SHIFT 8 4011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 4111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCFG1_MUX_MASK 0xf 4211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCFG1_SHIFT(chan) (4 * (chan)) 4311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 4411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa/* 4511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Each channel occupies 4 bits in TCON register, but there is a gap of 4 4611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * bits (one channel) after channel 0, so channels have different numbering 4711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * when accessing TCON register. See to_tcon_channel() function. 4811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * 4911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * In addition, the location of autoreload bit for channel 4 (TCON channel 5) 5011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * in its set of bits is 2 as opposed to 3 for other channels. 5111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 5211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCON_START(chan) BIT(4 * (chan) + 0) 5311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCON_MANUALUPDATE(chan) BIT(4 * (chan) + 1) 5411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCON_INVERT(chan) BIT(4 * (chan) + 2) 5511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define _TCON_AUTORELOAD(chan) BIT(4 * (chan) + 3) 5611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define _TCON_AUTORELOAD4(chan) BIT(4 * (chan) + 2) 5711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#define TCON_AUTORELOAD(chan) \ 5811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa ((chan < 5) ? _TCON_AUTORELOAD(chan) : _TCON_AUTORELOAD4(chan)) 5911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 6011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa/** 6111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * struct samsung_pwm_channel - private data of PWM channel 6211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @period_ns: current period in nanoseconds programmed to the hardware 6311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @duty_ns: current duty time in nanoseconds programmed to the hardware 6411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @tin_ns: time of one timer tick in nanoseconds with current timer rate 6511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 6611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastruct samsung_pwm_channel { 6711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 period_ns; 6811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 duty_ns; 6911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 tin_ns; 7011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 7111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 7211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa/** 7311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * struct samsung_pwm_chip - private data of PWM chip 7411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @chip: generic PWM chip 7511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @variant: local copy of hardware variant data 7611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @inverter_mask: inverter status for all channels - one bit per channel 7711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @base: base address of mapped PWM registers 7811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @base_clk: base clock used to drive the timers 7911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @tclk0: external clock 0 (can be ERR_PTR if not present) 8011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * @tclk1: external clock 1 (can be ERR_PTR if not present) 8111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 8211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastruct samsung_pwm_chip { 8311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct pwm_chip chip; 8411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_variant variant; 8511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u8 inverter_mask; 8611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 8711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa void __iomem *base; 8811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct clk *base_clk; 8911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct clk *tclk0; 9011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct clk *tclk1; 9111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 9211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 9311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#ifndef CONFIG_CLKSRC_SAMSUNG_PWM 9411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa/* 9511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * PWM block is shared between pwm-samsung and samsung_pwm_timer drivers 9611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * and some registers need access synchronization. If both drivers are 9711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * compiled in, the spinlock is defined in the clocksource driver, 9811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * otherwise following definition is used. 9911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * 10011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Currently we do not need any more complex synchronization method 10111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * because all the supported SoCs contain only one instance of the PWM 10211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * IP. Should this change, both drivers will need to be modified to 10311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * properly synchronize accesses to particular instances. 10411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 10511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic DEFINE_SPINLOCK(samsung_pwm_lock); 10611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#endif 10711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 10811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic inline 10911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastruct samsung_pwm_chip *to_samsung_pwm_chip(struct pwm_chip *chip) 11011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 11111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return container_of(chip, struct samsung_pwm_chip, chip); 11211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 11311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 11411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic inline unsigned int to_tcon_channel(unsigned int channel) 11511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 11611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* TCON register has a gap of 4 bits (1 channel) after channel 0 */ 11711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return (channel == 0) ? 0 : (channel + 1); 11811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 11911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 12011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic void pwm_samsung_set_divisor(struct samsung_pwm_chip *pwm, 12111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int channel, u8 divisor) 12211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 12311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u8 shift = TCFG1_SHIFT(channel); 12411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned long flags; 12511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 reg; 12611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u8 bits; 12711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 12811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa bits = (fls(divisor) - 1) - pwm->variant.div_base; 12911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 13011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_lock_irqsave(&samsung_pwm_lock, flags); 13111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 13211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg = readl(pwm->base + REG_TCFG1); 13311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg &= ~(TCFG1_MUX_MASK << shift); 13411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg |= bits << shift; 13511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa writel(reg, pwm->base + REG_TCFG1); 13611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 13711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_unlock_irqrestore(&samsung_pwm_lock, flags); 13811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 13911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 14011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_is_tdiv(struct samsung_pwm_chip *chip, unsigned int chan) 14111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 14211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_variant *variant = &chip->variant; 14311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 reg; 14411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 14511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg = readl(chip->base + REG_TCFG1); 14611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg >>= TCFG1_SHIFT(chan); 14711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg &= TCFG1_MUX_MASK; 14811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 14911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return (BIT(reg) & variant->tclk_mask) == 0; 15011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 15111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 15211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic unsigned long pwm_samsung_get_tin_rate(struct samsung_pwm_chip *chip, 15311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int chan) 15411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 15511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned long rate; 15611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 reg; 15711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 15811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa rate = clk_get_rate(chip->base_clk); 15911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 16011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg = readl(chip->base + REG_TCFG0); 16111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (chan >= 2) 16211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg >>= TCFG0_PRESCALER1_SHIFT; 16311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa reg &= TCFG0_PRESCALER_MASK; 16411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 16511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return rate / (reg + 1); 16611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 16711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 16811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *chip, 16911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int chan, unsigned long freq) 17011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 17111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_variant *variant = &chip->variant; 17211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned long rate; 17311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct clk *clk; 17411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u8 div; 17511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 17611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!pwm_samsung_is_tdiv(chip, chan)) { 17711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa clk = (chan < 2) ? chip->tclk0 : chip->tclk1; 17811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!IS_ERR(clk)) { 17911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa rate = clk_get_rate(clk); 18011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (rate) 18111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return rate; 18211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 18311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 18411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_warn(chip->chip.dev, 18511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa "tclk of PWM %d is inoperational, using tdiv\n", chan); 18611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 18711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 18811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa rate = pwm_samsung_get_tin_rate(chip, chan); 18911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_dbg(chip->chip.dev, "tin parent at %lu\n", rate); 19011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 19111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* 19211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Compare minimum PWM frequency that can be achieved with possible 19311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * divider settings and choose the lowest divisor that can generate 19411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * frequencies lower than requested. 19511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 19611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa for (div = variant->div_base; div < 4; ++div) 19711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if ((rate >> (variant->bits + div)) < freq) 19811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa break; 19911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 20011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa pwm_samsung_set_divisor(chip, chan, BIT(div)); 20111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 20211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return rate >> div; 20311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 20411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 20511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_request(struct pwm_chip *chip, struct pwm_device *pwm) 20611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 20711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip); 20811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_channel *our_chan; 20911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 21011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!(our_chip->variant.output_mask & BIT(pwm->hwpwm))) { 21111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_warn(chip->dev, 21211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa "tried to request PWM channel %d without output\n", 21311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa pwm->hwpwm); 21411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -EINVAL; 21511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 21611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 21711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa our_chan = devm_kzalloc(chip->dev, sizeof(*our_chan), GFP_KERNEL); 21811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!our_chan) 21911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -ENOMEM; 22011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 22111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa pwm_set_chip_data(pwm, our_chan); 22211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 22311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 22411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 22511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 22611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic void pwm_samsung_free(struct pwm_chip *chip, struct pwm_device *pwm) 22711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 22811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa devm_kfree(chip->dev, pwm_get_chip_data(pwm)); 229b577cdcf174b0e88091cb7c9926c44cda87d3d0dSachin Kamat pwm_set_chip_data(pwm, NULL); 23011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 23111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 23211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm) 23311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 23411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip); 23511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm); 23611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned long flags; 23711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 tcon; 23811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 23911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_lock_irqsave(&samsung_pwm_lock, flags); 24011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 24111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon = readl(our_chip->base + REG_TCON); 24211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 24311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon &= ~TCON_START(tcon_chan); 24411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon |= TCON_MANUALUPDATE(tcon_chan); 24511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa writel(tcon, our_chip->base + REG_TCON); 24611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 24711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon &= ~TCON_MANUALUPDATE(tcon_chan); 24811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon |= TCON_START(tcon_chan) | TCON_AUTORELOAD(tcon_chan); 24911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa writel(tcon, our_chip->base + REG_TCON); 25011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 25111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_unlock_irqrestore(&samsung_pwm_lock, flags); 25211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 25311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 25411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 25511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 25611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm) 25711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 25811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip); 25911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm); 26011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned long flags; 26111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 tcon; 26211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 26311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_lock_irqsave(&samsung_pwm_lock, flags); 26411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 26511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon = readl(our_chip->base + REG_TCON); 26611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon &= ~TCON_AUTORELOAD(tcon_chan); 26711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa writel(tcon, our_chip->base + REG_TCON); 26811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 26911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_unlock_irqrestore(&samsung_pwm_lock, flags); 27011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 27111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 27211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm, 27311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa int duty_ns, int period_ns) 27411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 27511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip); 27611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm); 27711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 tin_ns = chan->tin_ns, tcnt, tcmp; 27811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 27911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* 28011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * We currently avoid using 64bit arithmetic by using the 28111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * fact that anything faster than 1Hz is easily representable 28211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * by 32bits. 28311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 28411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (period_ns > NSEC_PER_SEC) 28511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -ERANGE; 28611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 28711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (period_ns == chan->period_ns && duty_ns == chan->duty_ns) 28811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 28911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 29011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm)); 29111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 29211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* We need tick count for calculation, not last tick. */ 29311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa ++tcnt; 29411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 29511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* Check to see if we are changing the clock rate of the PWM. */ 29611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (chan->period_ns != period_ns) { 29711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned long tin_rate; 29811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 period; 29911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 30011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa period = NSEC_PER_SEC / period_ns; 30111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 30211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_dbg(our_chip->chip.dev, "duty_ns=%d, period_ns=%d (%u)\n", 30311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa duty_ns, period_ns, period); 30411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 30511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tin_rate = pwm_samsung_calc_tin(our_chip, pwm->hwpwm, period); 30611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 30711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_dbg(our_chip->chip.dev, "tin_rate=%lu\n", tin_rate); 30811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 30911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tin_ns = NSEC_PER_SEC / tin_rate; 31011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcnt = period_ns / tin_ns; 31111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 31211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 31311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* Period is too short. */ 31411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (tcnt <= 1) 31511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -ERANGE; 31611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 31711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* Note that counters count down. */ 31811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcmp = duty_ns / tin_ns; 31911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 32011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* 0% duty is not available */ 32111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!tcmp) 32211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa ++tcmp; 32311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 32411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcmp = tcnt - tcmp; 32511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 32611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* Decrement to get tick numbers, instead of tick counts. */ 32711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa --tcnt; 32811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* -1UL will give 100% duty. */ 32911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa --tcmp; 33011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 33111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_dbg(our_chip->chip.dev, 33211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa "tin_ns=%u, tcmp=%u/%u\n", tin_ns, tcmp, tcnt); 33311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 33411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* Update PWM registers. */ 33511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa writel(tcnt, our_chip->base + REG_TCNTB(pwm->hwpwm)); 33611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa writel(tcmp, our_chip->base + REG_TCMPB(pwm->hwpwm)); 33711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 33811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chan->period_ns = period_ns; 33911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chan->tin_ns = tin_ns; 34011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chan->duty_ns = duty_ns; 34111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 34211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 34311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 34411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 34511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic void pwm_samsung_set_invert(struct samsung_pwm_chip *chip, 34611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int channel, bool invert) 34711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 34811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int tcon_chan = to_tcon_channel(channel); 34911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned long flags; 35011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 tcon; 35111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 35211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_lock_irqsave(&samsung_pwm_lock, flags); 35311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 35411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon = readl(chip->base + REG_TCON); 35511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 35611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (invert) { 35711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->inverter_mask |= BIT(channel); 35811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon |= TCON_INVERT(tcon_chan); 35911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } else { 36011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->inverter_mask &= ~BIT(channel); 36111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa tcon &= ~TCON_INVERT(tcon_chan); 36211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 36311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 36411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa writel(tcon, chip->base + REG_TCON); 36511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 36611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa spin_unlock_irqrestore(&samsung_pwm_lock, flags); 36711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 36811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 36911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_set_polarity(struct pwm_chip *chip, 37011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct pwm_device *pwm, 37111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa enum pwm_polarity polarity) 37211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 37311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip); 37411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa bool invert = (polarity == PWM_POLARITY_NORMAL); 37511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 37611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* Inverted means normal in the hardware. */ 37711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa pwm_samsung_set_invert(our_chip, pwm->hwpwm, invert); 37811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 37911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 38011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 38111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 38211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic const struct pwm_ops pwm_samsung_ops = { 38311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .request = pwm_samsung_request, 38411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .free = pwm_samsung_free, 38511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .enable = pwm_samsung_enable, 38611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .disable = pwm_samsung_disable, 38711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .config = pwm_samsung_config, 38811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .set_polarity = pwm_samsung_set_polarity, 38911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .owner = THIS_MODULE, 39011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 39111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 39211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#ifdef CONFIG_OF 39311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic const struct samsung_pwm_variant s3c24xx_variant = { 39411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .bits = 16, 39511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .div_base = 1, 39611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .has_tint_cstat = false, 39711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .tclk_mask = BIT(4), 39811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 39911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 40011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic const struct samsung_pwm_variant s3c64xx_variant = { 40111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .bits = 32, 40211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .div_base = 0, 40311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .has_tint_cstat = true, 40411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .tclk_mask = BIT(7) | BIT(6) | BIT(5), 40511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 40611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 40711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic const struct samsung_pwm_variant s5p64x0_variant = { 40811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .bits = 32, 40911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .div_base = 0, 41011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .has_tint_cstat = true, 41111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .tclk_mask = 0, 41211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 41311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 41411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic const struct samsung_pwm_variant s5pc100_variant = { 41511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .bits = 32, 41611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .div_base = 0, 41711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .has_tint_cstat = true, 41811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .tclk_mask = BIT(5), 41911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 42011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 42111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic const struct of_device_id samsung_pwm_matches[] = { 42211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa { .compatible = "samsung,s3c2410-pwm", .data = &s3c24xx_variant }, 42311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa { .compatible = "samsung,s3c6400-pwm", .data = &s3c64xx_variant }, 42411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa { .compatible = "samsung,s5p6440-pwm", .data = &s5p64x0_variant }, 42511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa { .compatible = "samsung,s5pc100-pwm", .data = &s5pc100_variant }, 42611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa { .compatible = "samsung,exynos4210-pwm", .data = &s5p64x0_variant }, 42711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa {}, 42811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 42911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 43011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_parse_dt(struct samsung_pwm_chip *chip) 43111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 43211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct device_node *np = chip->chip.dev->of_node; 43311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa const struct of_device_id *match; 43411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct property *prop; 43511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa const __be32 *cur; 43611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa u32 val; 43711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 43811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa match = of_match_node(samsung_pwm_matches, np); 43911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!match) 44011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -ENODEV; 44111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 44211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa memcpy(&chip->variant, match->data, sizeof(chip->variant)); 44311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 44411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa of_property_for_each_u32(np, "samsung,pwm-outputs", prop, cur, val) { 44511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (val >= SAMSUNG_PWM_NUM) { 44611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_err(chip->chip.dev, 44711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa "%s: invalid channel index in samsung,pwm-outputs property\n", 44811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa __func__); 44911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa continue; 45011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 45111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->variant.output_mask |= BIT(val); 45211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 45311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 45411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 45511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 45611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#else 45711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_parse_dt(struct samsung_pwm_chip *chip) 45811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 45911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -ENODEV; 46011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 46111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#endif 46211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 46311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_probe(struct platform_device *pdev) 46411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 46511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct device *dev = &pdev->dev; 46611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *chip; 46711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct resource *res; 46811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int chan; 46911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa int ret; 47011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 47111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); 47211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (chip == NULL) 47311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -ENOMEM; 47411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 47511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->chip.dev = &pdev->dev; 47611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->chip.ops = &pwm_samsung_ops; 47711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->chip.base = -1; 47811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->chip.npwm = SAMSUNG_PWM_NUM; 47911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->inverter_mask = BIT(SAMSUNG_PWM_NUM) - 1; 48011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 48111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { 48211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa ret = pwm_samsung_parse_dt(chip); 48311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (ret) 48411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return ret; 48511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 48611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->chip.of_xlate = of_pwm_xlate_with_flags; 48711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->chip.of_pwm_n_cells = 3; 48811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } else { 48911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!pdev->dev.platform_data) { 49011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_err(&pdev->dev, "no platform data specified\n"); 49111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return -EINVAL; 49211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 49311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 49411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa memcpy(&chip->variant, pdev->dev.platform_data, 49511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa sizeof(chip->variant)); 49611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 49711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 49811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 49911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->base = devm_ioremap_resource(&pdev->dev, res); 50011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (IS_ERR(chip->base)) 50111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return PTR_ERR(chip->base); 50211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 50311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->base_clk = devm_clk_get(&pdev->dev, "timers"); 50411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (IS_ERR(chip->base_clk)) { 50511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_err(dev, "failed to get timer base clk\n"); 50611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return PTR_ERR(chip->base_clk); 50711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 50811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 50911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa ret = clk_prepare_enable(chip->base_clk); 51011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (ret < 0) { 51111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_err(dev, "failed to enable base clock\n"); 51211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return ret; 51311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 51411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 51511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa for (chan = 0; chan < SAMSUNG_PWM_NUM; ++chan) 51611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (chip->variant.output_mask & BIT(chan)) 51711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa pwm_samsung_set_invert(chip, chan, true); 51811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 51911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* Following clocks are optional. */ 52011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->tclk0 = devm_clk_get(&pdev->dev, "pwm-tclk0"); 52111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->tclk1 = devm_clk_get(&pdev->dev, "pwm-tclk1"); 52211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 52311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa platform_set_drvdata(pdev, chip); 52411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 52511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa ret = pwmchip_add(&chip->chip); 52611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (ret < 0) { 52711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_err(dev, "failed to register PWM chip\n"); 52811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa clk_disable_unprepare(chip->base_clk); 52911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return ret; 53011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 53111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 53211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa dev_dbg(dev, "base_clk at %lu, tclk0 at %lu, tclk1 at %lu\n", 53311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa clk_get_rate(chip->base_clk), 53411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa !IS_ERR(chip->tclk0) ? clk_get_rate(chip->tclk0) : 0, 53511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa !IS_ERR(chip->tclk1) ? clk_get_rate(chip->tclk1) : 0); 53611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 53711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 53811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 53911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 54011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_remove(struct platform_device *pdev) 54111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 54211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *chip = platform_get_drvdata(pdev); 54311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa int ret; 54411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 54511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa ret = pwmchip_remove(&chip->chip); 54611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (ret < 0) 54711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return ret; 54811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 54911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa clk_disable_unprepare(chip->base_clk); 55011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 55111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 55211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 55311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 55411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#ifdef CONFIG_PM_SLEEP 55511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_suspend(struct device *dev) 55611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 55711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *chip = dev_get_drvdata(dev); 55811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int i; 55911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 56011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* 56111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * No one preserves these values during suspend so reset them. 56211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Otherwise driver leaves PWM unconfigured if same values are 56311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * passed to pwm_config() next time. 56411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 56511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa for (i = 0; i < SAMSUNG_PWM_NUM; ++i) { 56611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct pwm_device *pwm = &chip->chip.pwms[i]; 56711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm); 56811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 56911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (!chan) 57011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa continue; 57111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 57211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chan->period_ns = 0; 57311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chan->duty_ns = 0; 57411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 57511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 57611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 57711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 57811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 57911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic int pwm_samsung_resume(struct device *dev) 58011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa{ 58111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa struct samsung_pwm_chip *chip = dev_get_drvdata(dev); 58211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa unsigned int chan; 58311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 58411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa /* 58511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * Inverter setting must be preserved across suspend/resume 58611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa * as nobody really seems to configure it more than once. 58711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa */ 58811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa for (chan = 0; chan < SAMSUNG_PWM_NUM; ++chan) { 58911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa if (chip->variant.output_mask & BIT(chan)) 59011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa pwm_samsung_set_invert(chip, chan, 59111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa chip->inverter_mask & BIT(chan)); 59211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa } 59311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 59411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa return 0; 59511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa} 59611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa#endif 59711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 5984407b6d243293e84546f4b1dbbe1ed8e9d797a6cJingoo Hanstatic SIMPLE_DEV_PM_OPS(pwm_samsung_pm_ops, pwm_samsung_suspend, 5994407b6d243293e84546f4b1dbbe1ed8e9d797a6cJingoo Han pwm_samsung_resume); 60011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 60111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figastatic struct platform_driver pwm_samsung_driver = { 60211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .driver = { 60311ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .name = "samsung-pwm", 60411ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .owner = THIS_MODULE, 60511ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .pm = &pwm_samsung_pm_ops, 60611ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .of_match_table = of_match_ptr(samsung_pwm_matches), 60711ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa }, 60811ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .probe = pwm_samsung_probe, 60911ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa .remove = pwm_samsung_remove, 61011ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa}; 61111ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figamodule_platform_driver(pwm_samsung_driver); 61211ad39ede24ee42909d58dc95031d96da46e33bdTomasz Figa 61311ad39ede24ee42909d58dc95031d96da46e33bdTomasz FigaMODULE_LICENSE("GPL"); 61411ad39ede24ee42909d58dc95031d96da46e33bdTomasz FigaMODULE_AUTHOR("Tomasz Figa <tomasz.figa@gmail.com>"); 61511ad39ede24ee42909d58dc95031d96da46e33bdTomasz FigaMODULE_ALIAS("platform:samsung-pwm"); 616