Exemple #1
0
int ehrpwm_aq_set_act_ctrl(struct pwm_device *p, struct aq_config_params *cfg)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	unsigned char reg;

	if (!cfg)
		return -EINVAL;

	if (cfg->ch > 1 || cfg->ctreqzro > 3 || cfg->ctreqprd > 3 ||
		cfg->ctreqcmpaup > 3 || cfg->ctreqcmpadown > 3 ||
		cfg->ctreqcmpbup > 3 || cfg->ctreqcmpbdown > 3)
		return -EINVAL;

	if (cfg->ch == 0)
		reg = AQCTLA;
	else
		reg = AQCTLB;

	ehrpwm_reg_config(ehrpwm, reg, cfg->ctreqzro, ACTCTL_CZRO_MASK);
	ehrpwm_reg_config(ehrpwm, reg, cfg->ctreqprd << ACTCTL_CTREQPRD_POS,
		       ACTCTL_CPRD_MASK);
	ehrpwm_reg_config(ehrpwm, reg, cfg->ctreqcmpaup <<
		       ACTCTL_CTREQCMPAUP_POS, ACTCTL_CAU_MASK);
	ehrpwm_reg_config(ehrpwm, reg, cfg->ctreqcmpadown <<
		       ACTCTL_CTREQCMPADN_POS, ACTCTL_CAD_MASK);
	ehrpwm_reg_config(ehrpwm, reg, cfg->ctreqcmpbup <<
		       ACTCTL_CTREQCMPBUP_POS, ACTCTL_CBU_MASK);
	ehrpwm_reg_config(ehrpwm, reg, cfg->ctreqcmpbdown <<
		       ACTCTL_CTREQCMPBDN_POS, ACTCTL_CBD_MASK);

	return 0;
}
Exemple #2
0
int ehrpwm_hr_config(struct pwm_device *p, unsigned char loadmode,
		unsigned char ctlmode, unsigned char edgemode)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (loadmode > 1 || ctlmode > 1 || edgemode > 3)
		return -EINVAL;

	if (ehrpwm->version == PWM_VERSION_1) {
		ehrpwm_reg_config(ehrpwm, AM335X_HRCNFG,
				loadmode << HRCNFG_LDMD_POS, BIT(3));
		ehrpwm_reg_config(ehrpwm, AM335X_HRCNFG,
				ctlmode << HRCNFG_CTLMD_POS, BIT(2));
		ehrpwm_reg_config(ehrpwm, AM335X_HRCNFG,
				edgemode, HRCNFG_EDGEMD_MASK);
	} else {
		ehrpwm_reg_config(ehrpwm, HRCNFG,
				loadmode << HRCNFG_LDMD_POS, BIT(3));
		ehrpwm_reg_config(ehrpwm, HRCNFG,
				ctlmode << HRCNFG_CTLMD_POS, BIT(2));
		ehrpwm_reg_config(ehrpwm, HRCNFG,
				edgemode, HRCNFG_EDGEMD_MASK);
	}

	return 0;
}
Exemple #3
0
static int ehrpwm_pwm_set_dty(struct pwm_device *p)
{
	unsigned short duty_ticks = 0;
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	int ret = 0;
	int chan;

	chan = p - &ehrpwm->pwm[0];

	if (!ehrpwm->prescale_val) {
		dev_dbg(p->dev, "%s: prescale_val is zero\n", __func__);
		return -EINVAL;
	}

	duty_ticks = p->duty_ticks / ehrpwm->prescale_val;
	debug("\n Prescaler value is %d", ehrpwm->prescale_val);
	debug("\n duty ticks is %d", duty_ticks);
	pm_runtime_get_sync(ehrpwm->dev);
	/* High resolution module */
	if (chan && ehrpwm->prescale_val <= 1) {
		ret = ehrpwm_hr_duty_config(p);
		if (ehrpwm->version == PWM_VERSION_1)
			ehrpwm_write(ehrpwm, AM335X_HRCNFG, 0x2);
		else
			ehrpwm_write(ehrpwm, HRCNFG, 0x2);
	}

	ehrpwm_write(ehrpwm, (chan ? CMPB : CMPA), duty_ticks);
	pm_runtime_put_sync(ehrpwm->dev);
	return ret;
}
Exemple #4
0
static int ehrpwm_hr_duty_config(struct pwm_device *p)
{
	unsigned char no_of_mepsteps;
	unsigned short cmphr_val;
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (!p->tick_hz) {
		dev_dbg(p->dev, "%s: p->tick_hz is zero\n", __func__);
		return -EINVAL;
	}

	/*
	 * Calculate the no of MEP steps. Assume system clock
	 * is in the order of MHZ.
	 */
	no_of_mepsteps = USEC_PER_SEC / ((p->tick_hz / USEC_PER_SEC) * 63);

	pm_runtime_get_sync(ehrpwm->dev);
	/* Calculate the CMPHR Value */
	cmphr_val = p->tick_hz / USEC_PER_SEC;
	cmphr_val = (p->duty_ns * cmphr_val) % MSEC_PER_SEC;
	cmphr_val = (cmphr_val * no_of_mepsteps) / 1000;
	cmphr_val = (cmphr_val << 8) + 0x180;
	ehrpwm_write(ehrpwm, CMPAHR, cmphr_val);

	if (ehrpwm->version == PWM_VERSION_1)
		ehrpwm_write(ehrpwm, AM335X_HRCNFG, 0x2);
	else
		ehrpwm_write(ehrpwm, HRCNFG, 0x2);

	pm_runtime_put_sync(ehrpwm->dev);
	return 0;
}
Exemple #5
0
static int ehrpwm_pwm_set_pol(struct pwm_device *p)
{
	unsigned int act_ctrl_reg;
	unsigned int cmp_reg;
	unsigned int ctreqcmp_mask;
	unsigned int ctreqcmp;
	unsigned short val;
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	int chan;

	chan = p - &ehrpwm->pwm[0];
	if (!chan) {
		act_ctrl_reg = AQCTLA;
		cmp_reg = CMPA;
		ctreqcmp_mask = ACTCTL_CAU_MASK;
		ctreqcmp = 4;
	} else {
		act_ctrl_reg = AQCTLB;
		cmp_reg = CMPB;
		ctreqcmp_mask = ACTCTL_CBU_MASK;
		ctreqcmp = 8;
	}


	pm_runtime_get_sync(ehrpwm->dev);
	val = ((p->active_high ? ACTCTL_CTREQCMP_HIGH : ACTCTL_CTREQCMP_LOW)
		 << ctreqcmp) | (p->active_high ? ACTCTL_CTREQZRO_LOW :
			ACTCTL_CTREQZRO_HIGH);
	ehrpwm_write(ehrpwm, act_ctrl_reg, val);
	pm_runtime_put_sync(ehrpwm->dev);
	return 0;
}
static int ehrpwm_pwm_start(struct pwm_device *p)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	unsigned short val;
	unsigned short read_val1;
	unsigned short read_val2;
	int chan;

	chan = p - &ehrpwm->pwm[0];
	val = ehrpwm_read(ehrpwm, TBCTL);
	val = (val & ~TBCTL_CTRMODE_MASK) | (TBCTL_CTRMOD_CTRUP |
		 TBCTL_FREERUN_FREE << 14);
	ehrpwm_write(ehrpwm, TBCTL, val);
	ehrpwm_tz_set_action(p, chan, 0x3);
	read_val1 = ehrpwm_read(ehrpwm, TZFLG);
	read_val2 = ehrpwm_read(ehrpwm, TZCTL);
	/*
	 * State of the other channel is determined by reading the
	 * TZCTL register. If the other channel is also in running state,
	 * one shot event status is cleared, otherwise one shot action for
	 * this channel is set to "DO NOTHING.
	 */
	read_val2 = read_val2 & (chan ? 0x3 : (0x3 << 2));
	read_val2 = chan ? read_val2 : (read_val2 >> 2);
	if (!(read_val1 & 0x4) || (read_val2 == 0x3))
		ehrpwm_tz_clr_evt_status(p);
	set_bit(FLAG_RUNNING, &p->flags);

	return 0;
}
Exemple #7
0
int ehrpwm_db_get_delay(struct pwm_device *p, unsigned char edge,
	enum config_mask cfgmask, unsigned long *delay_val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	unsigned long delay_ns;
	unsigned long delay_ticks;
	unsigned char offset;

	if (!ehrpwm)
		return -EINVAL;

	if (edge == RISING_EDGE_DELAY)
		offset = DBRED;
	else if (edge == FALLING_EDGE_DELAY)
		offset = DBFED;
	else
		return -EINVAL;

	delay_ticks = ehrpwm_read(ehrpwm, offset);
	/* Only least 10 bits are required */
	delay_ticks = delay_ticks & 0x3ff;
	if (cfgmask == CONFIG_TICKS) {
		*delay_val = delay_ticks * ehrpwm->prescale_val;
	} else if (cfgmask == CONFIG_NS) {
		delay_ticks = delay_ticks * ehrpwm->prescale_val;
		delay_ns = pwm_ticks_to_ns(p, delay_ticks);
		debug("\n delay ns value is %lu", delay_ns);
		*delay_val = delay_ns;
	} else {
		return -EINVAL;
	}

	return 0;
}
Exemple #8
0
static int ehrpwm_pwm_start(struct pwm_device *p)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	unsigned short val;
	int chan;

	/* Trying to start a running PWM, not allowed */
	if (pwm_is_running(p))
		return -EPERM;

	/* For PWM clock should be enabled on start */
	pm_runtime_get_sync(ehrpwm->dev);

	ehrpwm_pwm_set_pol(p);
	chan = p - &ehrpwm->pwm[0];
	val = ehrpwm_read(ehrpwm, TBCTL);
	val = (val & ~TBCTL_CTRMODE_MASK) | (TBCTL_CTRMOD_CTRUP |
		 TBCTL_FREERUN_FREE << 14);
	ehrpwm_write(ehrpwm, TBCTL, val);

	/* Enable PWM channel output */
	ehrpwm_channel_output_enable(p, chan);

	set_bit(FLAG_RUNNING, &p->flags);
	return 0;
}
Exemple #9
0
int ehrpwm_tb_set_phase(struct pwm_device *p, unsigned short val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	ehrpwm_write(ehrpwm, TBPHS, val);

	return 0;
}
Exemple #10
0
int ehrpwm_tb_read_counter(struct pwm_device *p, unsigned short *val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	*val = ehrpwm_read(ehrpwm, TBCTR);

	return 0;
}
Exemple #11
0
int ehrpwm_tb_read_status(struct pwm_device *p, unsigned short *val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	*val = ehrpwm_read(ehrpwm, TBSTS);

	return 0;
}
Exemple #12
0
int ehrpwm_tb_force_sync(struct pwm_device *p)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	ehrpwm_reg_config(ehrpwm, TBCTL, ENABLE << TBCTL_FRC_SYC_POS, BIT(6));

	return 0;
}
Exemple #13
0
inline int ehrpwm_tz_read_status(struct pwm_device *p, unsigned short *status)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	*status = ehrpwm_read(ehrpwm, TZFLG);

	return 0;
}
Exemple #14
0
inline int ehrpwm_hr_set_cmpval(struct pwm_device *p, unsigned char val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	ehrpwm_write(ehrpwm, CMPAHR, val << 8);

	return 0;
}
Exemple #15
0
inline int ehrpwm_et_clr_int(struct pwm_device *p)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	ehrpwm_write(ehrpwm, ETCLR, ENABLE);

	return 0;
}
Exemple #16
0
/* High Resolution Module configuration */
inline int ehrpwm_hr_set_phase(struct pwm_device *p, unsigned char val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	ehrpwm_write(ehrpwm, TBPHSHR, val << 8);

	return 0;
}
Exemple #17
0
inline int ehrpwm_tz_clr_int_status(struct pwm_device *p)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	ehrpwm_write(ehrpwm, TZCLR, 0x1);

	return 0;
}
Exemple #18
0
inline int ehrpwm_et_int_en_dis(struct pwm_device *p, unsigned char en_dis)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	ehrpwm_reg_config(ehrpwm, ETSEL, en_dis << ETSEL_EN_INT_EN_POS, BIT(3));

	return 0;
}
Exemple #19
0
static void ehrpwm_channel_output_low(struct pwm_device *p)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	int chan = p - &ehrpwm->pwm[0];

	ehrpwm_aq_set_csfrc_load_mode(p, AQSFRC_RLDCSF_IMDT);
	ehrpwm_aq_continuous_frc(p, chan, AQCSFRC_CSF_FRCLOW);
}
Exemple #20
0
static void ehrpwm_channel_output_enable(struct pwm_device *p, int channel)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	pm_runtime_get_sync(ehrpwm->dev);
	ehrpwm_aq_set_csfrc_load_mode(p, AQSFRC_RLDCSF_ZRO);
	ehrpwm_aq_continuous_frc(p, channel, AQCSFRC_CSF_FRCDIS);
	pm_runtime_put_sync(ehrpwm->dev);
}
Exemple #21
0
inline int ehrpwm_et_read_int_status(struct pwm_device *p,
	unsigned long *status)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	*status = ehrpwm_read(ehrpwm, ETFLG) & BIT(0);

	return 0;
}
Exemple #22
0
inline int ehrpwm_et_read_evt_cnt(struct pwm_device *p,
	unsigned long *evtcnt)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	*evtcnt = ehrpwm_read(ehrpwm, ETPS) & ETPS_INTCNT_MASK;
	*evtcnt >>= 0x2;

	return 0;
}
Exemple #23
0
inline int ehrpwm_tz_clr_evt_status(struct pwm_device *p)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	unsigned short ret;

	ret = ehrpwm_read(ehrpwm, TZFLG);
	ehrpwm_write(ehrpwm, TZCLR, ret & ~0x1);

	return 0;
}
Exemple #24
0
int ehrpwm_tb_set_periodload(struct pwm_device *p, unsigned char loadmode)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (loadmode > 0x1)
		return -EINVAL;

	ehrpwm_reg_config(ehrpwm, TBCTL, loadmode << TBCTL_LOAD_MD_POS, BIT(3));

	return 0;
}
Exemple #25
0
int ehrpwm_pc_en_dis(struct pwm_device *p, unsigned char chpen)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (chpen > 1)
		return -EINVAL;

	ehrpwm_reg_config(ehrpwm, PCCTL, chpen, BIT(0));

	return 0;
}
inline int ehrpwm_reg_write(struct pwm_device *p, unsigned int reg,
	       unsigned short val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (reg > HRCNFG)
		return -EINVAL;

	ehrpwm_write(ehrpwm, reg, val);

	return 0;
}
inline int ehrpwm_reg_read(struct pwm_device *p, unsigned int reg,
	       unsigned short *val)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (reg > HRCNFG)
		return -EINVAL;

	*val = ehrpwm_read(ehrpwm, reg);

	return 0;
}
Exemple #28
0
static int ehrpwm_pwm_set_prd(struct pwm_device *p)
{
	unsigned int ps_div_val = 1;
	unsigned int tb_div_val = 0;
	char ret;
	unsigned short val;
	unsigned short period_ticks;
	struct pwm_device *temp;
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);
	int chan = 0;
	/*
	 * Since the device has a singe period register, copy the period
	 * value to the other channel also.
	 */
	chan = p - &ehrpwm->pwm[0];
	temp = &ehrpwm->pwm[!chan];
	temp->period_ticks = p->period_ticks;
	temp->period_ns = p->period_ns;
	debug("\n period_ticks is %lu", p->period_ticks);

	if (p->period_ticks > 65535) {
		ret = get_divider_val(p->period_ticks / 65535 + 1, &ps_div_val,
				&tb_div_val);
		if (ret) {
			dev_err(p->dev, "failed to get the divider value");
			return -EINVAL;
		}
	}

	pm_runtime_get_sync(ehrpwm->dev);
	val = ehrpwm_read(ehrpwm, TBCTL);
	val = (val & ~TBCTL_CLKDIV_MASK & ~TBCTL_HSPCLKDIV_MASK) | tb_div_val;
	ehrpwm_write(ehrpwm, TBCTL, val);
	period_ticks = p->period_ticks / ps_div_val;

	if (period_ticks <= 1) {
		dev_err(p->dev, "Required period/frequency cannot be obtained");
		pm_runtime_put_sync(ehrpwm->dev);
		return -EINVAL;
	}
	/*
	 * Program the period register with 1 less than the actual value since
	 * the module generates waveform with period always 1 greater
	 * the programmed value.
	 */
	ehrpwm_write(ehrpwm, TBPRD, (unsigned short)(period_ticks - 1));
	pm_runtime_put_sync(ehrpwm->dev);
	debug("\n period_ticks is %d", period_ticks);
	ehrpwm->prescale_val = ps_div_val;
	debug("\n Prescaler value is %d", ehrpwm->prescale_val);

	return 0;
}
Exemple #29
0
int ehrpwm_aq_set_csfrc_load_mode(struct pwm_device *p, unsigned char loadmode)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (loadmode > 0x3)
		return -EINVAL;

	ehrpwm_reg_config(ehrpwm, AQSFRC, loadmode << AQSFRC_LDMD_POS,
		       AQSFRC_CFRC_LOAD_MASK);

	return 0;
}
Exemple #30
0
/* Event Trigger Configuration functions */
int ehrpwm_et_set_sel_evt(struct pwm_device *p, unsigned char evt,
		unsigned char prd)
{
	struct ehrpwm_pwm *ehrpwm = to_ehrpwm_pwm(p);

	if (evt > 0x7 || prd > 0x3)
		return -EINVAL;

	ehrpwm_reg_config(ehrpwm, ETSEL, evt, ETSEL_INTSEL_MASK);
	ehrpwm_reg_config(ehrpwm, ETPS, prd, ETPS_INTPRD_MASK);

	return 0;
}