blob: 3065323ebf91340be0fa5f76e55dc3330e44cb24 [file] [log] [blame]
/*
* include/linux/amlogic/pwm_meson.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#ifndef _PWM_MESON_H
#define _PWM_MESON_H
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/export.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/time.h>
#include <linux/clk.h>
#include <linux/of_address.h>
#include <linux/amlogic/cpu_version.h>
#include <linux/clk-provider.h>
/* for pwm channel index*/
#include <dt-bindings/pwm/meson.h>
/*a group pwm registers offset address
* for example:
* PWM A B
* PWM C D
* PWM E F
* PWM AO A
* PWM AO B
*/
#define REG_PWM_A 0x0
#define REG_PWM_B 0x4
#define REG_MISC_AB 0x8
#define REG_DS_AB 0xc
#define REG_TIME_AB 0x10
#define REG_PWM_A2 0x14
#define REG_PWM_B2 0x18
#define REG_BLINK_AB 0x1c
/* pwm output enable */
#define MISC_A_EN BIT(0)
#define MISC_B_EN BIT(1)
#define MISC_A2_EN BIT(25)
#define MISC_B2_EN BIT(24)
/* pwm polarity enable */
#define MISC_A_INVERT BIT(26)
#define MISC_B_INVERT BIT(27)
/* when you want 0% or 100% waveform
* constant bit should be set.
*/
#define MISC_A_CONSTANT BIT(28)
#define MISC_B_CONSTANT BIT(29)
/*
* pwm a and b clock enable/disable
*/
#define MISC_A_CLK_EN BIT(15)
#define MISC_B_CLK_EN BIT(23)
/*
* blink control bit
*/
#define BLINK_A BIT(8)
#define BLINK_B BIT(9)
#define PWM_HIGH_SHIFT 16
#define MISC_CLK_DIV_MASK 0x7f
#define MISC_B_CLK_DIV_SHIFT 16
#define MISC_A_CLK_DIV_SHIFT 8
#define MISC_B_CLK_SEL_SHIFT 6
#define MISC_A_CLK_SEL_SHIFT 4
#define MISC_CLK_SEL_WIDTH 2
#define PWM_CHANNELS_PER_GROUP 2
static const unsigned int mux_reg_shifts[] = {
MISC_A_CLK_SEL_SHIFT,
MISC_B_CLK_SEL_SHIFT,
MISC_A_CLK_SEL_SHIFT,
MISC_B_CLK_SEL_SHIFT
};
/*pwm register att*/
struct meson_pwm_variant {
unsigned int times;
unsigned int constant;
unsigned int blink_enable;
unsigned int blink_times;
};
/*for soc data:
*double channel enable
* double_channel = false ,could use PWM A
* double_channel = true , could use PWM A and PWM A2
*/
struct meson_pwm_data {
bool double_channel;
const char * const *parent_names;
};
struct meson_pwm {
struct pwm_chip chip;
void __iomem *base;
struct meson_pwm_data *data;
struct meson_pwm_variant variant;
u32 inverter_mask;
struct mutex lock;
spinlock_t pwm_lock;
unsigned int clk_mask;
};
/*the functions only use for meson pwm driver*/
void pwm_set_reg_bits(void __iomem *reg,
unsigned int mask,
const unsigned int val);
void pwm_write_reg(void __iomem *reg,
const unsigned int val);
void pwm_clear_reg_bits(void __iomem *reg, const unsigned int val);
void pwm_write_reg1(void __iomem *reg, const unsigned int val);
int meson_pwm_sysfs_init(struct device *dev);
void meson_pwm_sysfs_exit(struct device *dev);
#if IS_ENABLED(CONFIG_AMLOGIC_PWM)
int pwm_register_debug(struct meson_pwm *meson);
struct meson_pwm *to_meson_pwm(struct pwm_chip *chip);
int pwm_constant_enable(struct meson_pwm *meson, int index);
int pwm_constant_disable(struct meson_pwm *meson, int index);
int pwm_blink_enable(struct meson_pwm *meson, int index);
int pwm_blink_disable(struct meson_pwm *meson, int index);
int pwm_set_blink_times(struct meson_pwm *meson,
int index,
int value);
int pwm_set_times(struct meson_pwm *meson,
int index, int value);
#else
static inline int pwm_register_debug
(struct meson_pwm *meson)
{
return -EINVAL;
}
struct meson_pwm *to_meson_pwm(struct pwm_chip *chip)
{
return NULL;
}
static inline int pwm_constant_enable
(struct meson_pwm *meson, int index)
{
return -EINVAL;
}
static inline int pwm_constant_disable
(struct meson_pwm *meson, int index)
{
return -EINVAL;
}
static inline int pwm_blink_enable
(struct meson_pwm *meson, int index)
{
return -EINVAL;
}
static inline int pwm_blink_disable
(struct meson_pwm *meson, int index)
{
return -EINVAL;
}
static inline int pwm_set_blink_times(struct meson_pwm *meson,
int index,
int value);
{
return -EINVAL;
}
static inline int pwm_set_times(struct meson_pwm *meson,
int index, int value)
{
return -EINVAL;
}
#endif /* IS_ENABLED(CONFIG_PWM_MESON) */
#endif /* _PWM_MESON_H_ */