Skip to content

Commit

Permalink
ARM: 5628/1: ep93xx: Introduce Pulse Width Modulator (PWM) driver
Browse files Browse the repository at this point in the history
The EP93xx features two PWMs (one on the EP9307) with the following
features:

  * Configurable dual output
  * Separate input clocks for each PWM output
  * 16-bit resolution
  * Programmable pulse width (duty cycle), interval (frequency), and
    polarity

This adds the necessary core support as well as the driver.  A sysfs
interface is provided to control the PWM outputs.

Signed-off-by: Matthieu Crapet <mcrapet@gmail.com>
Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Acked-by: Ryan Mallon <ryan@bluewatersys.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Hartley Sweeten authored and Russell King committed Jul 30, 2009
1 parent 3aa7a9a commit ef12379
Show file tree
Hide file tree
Showing 7 changed files with 492 additions and 0 deletions.
4 changes: 4 additions & 0 deletions arch/arm/mach-ep93xx/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ static struct clk clk_keypad = {
.enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
.set_rate = set_keytchclk_rate,
};
static struct clk clk_pwm = {
.rate = EP93XX_EXT_CLK_RATE,
};

/* DMA Clocks */
static struct clk clk_m2p0 = {
Expand Down Expand Up @@ -137,6 +140,7 @@ static struct clk_lookup clocks[] = {
INIT_CK(NULL, "pll2", &clk_pll2),
INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
INIT_CK(NULL, "pwm_clk", &clk_pwm),
INIT_CK(NULL, "m2p0", &clk_m2p0),
INIT_CK(NULL, "m2p1", &clk_m2p1),
INIT_CK(NULL, "m2p2", &clk_m2p2),
Expand Down
85 changes: 85 additions & 0 deletions arch/arm/mach-ep93xx/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,91 @@ static struct platform_device ep93xx_leds = {
};


/*************************************************************************
* EP93xx pwm peripheral handling
*************************************************************************/
static struct resource ep93xx_pwm0_resource[] = {
{
.start = EP93XX_PWM_PHYS_BASE,
.end = EP93XX_PWM_PHYS_BASE + 0x10 - 1,
.flags = IORESOURCE_MEM,
},
};

static struct platform_device ep93xx_pwm0_device = {
.name = "ep93xx-pwm",
.id = 0,
.num_resources = ARRAY_SIZE(ep93xx_pwm0_resource),
.resource = ep93xx_pwm0_resource,
};

static struct resource ep93xx_pwm1_resource[] = {
{
.start = EP93XX_PWM_PHYS_BASE + 0x20,
.end = EP93XX_PWM_PHYS_BASE + 0x30 - 1,
.flags = IORESOURCE_MEM,
},
};

static struct platform_device ep93xx_pwm1_device = {
.name = "ep93xx-pwm",
.id = 1,
.num_resources = ARRAY_SIZE(ep93xx_pwm1_resource),
.resource = ep93xx_pwm1_resource,
};

void __init ep93xx_register_pwm(int pwm0, int pwm1)
{
if (pwm0)
platform_device_register(&ep93xx_pwm0_device);

/* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */
if (pwm1)
platform_device_register(&ep93xx_pwm1_device);
}

int ep93xx_pwm_acquire_gpio(struct platform_device *pdev)
{
int err;

if (pdev->id == 0) {
err = 0;
} else if (pdev->id == 1) {
err = gpio_request(EP93XX_GPIO_LINE_EGPIO14,
dev_name(&pdev->dev));
if (err)
return err;
err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0);
if (err)
goto fail;

/* PWM 1 output on EGPIO[14] */
ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG);
} else {
err = -ENODEV;
}

return err;

fail:
gpio_free(EP93XX_GPIO_LINE_EGPIO14);
return err;
}
EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio);

void ep93xx_pwm_release_gpio(struct platform_device *pdev)
{
if (pdev->id == 1) {
gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14);
gpio_free(EP93XX_GPIO_LINE_EGPIO14);

/* EGPIO[14] used for GPIO */
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG);
}
}
EXPORT_SYMBOL(ep93xx_pwm_release_gpio);


extern void ep93xx_gpio_init(void);

void __init ep93xx_init_devices(void)
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000)
#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000)

#define EP93XX_PWM_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00110000)
#define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000)

#define EP93XX_RTC_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00120000)
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/mach-ep93xx/include/mach/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef __ASSEMBLY__

struct i2c_board_info;
struct platform_device;

struct ep93xx_eth_data
{
Expand Down Expand Up @@ -32,6 +33,9 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)

void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
void ep93xx_register_pwm(int pwm0, int pwm1);
int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
void ep93xx_pwm_release_gpio(struct platform_device *pdev);

void ep93xx_init_devices(void);
extern struct sys_timer ep93xx_timer;
Expand Down
13 changes: 13 additions & 0 deletions drivers/misc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ config ISL29003
This driver can also be built as a module. If so, the module
will be called isl29003.

config EP93XX_PWM
tristate "EP93xx PWM support"
depends on ARCH_EP93XX
help
This option enables device driver support for the PWM channels
on the Cirrus EP93xx processors. The EP9307 chip only has one
PWM channel all the others have two, the second channel is an
alternate function of the EGPIO14 pin. A sysfs interface is
provided to control the PWM channels.

To compile this driver as a module, choose M here: the module will
be called ep93xx_pwm.

source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
Expand Down
1 change: 1 addition & 0 deletions drivers/misc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ obj-$(CONFIG_SGI_XP) += sgi-xp/
obj-$(CONFIG_SGI_GRU) += sgi-gru/
obj-$(CONFIG_HP_ILO) += hpilo.o
obj-$(CONFIG_ISL29003) += isl29003.o
obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
obj-$(CONFIG_C2PORT) += c2port/
obj-y += eeprom/
obj-y += cb710/
Loading

0 comments on commit ef12379

Please sign in to comment.