summaryrefslogtreecommitdiff
path: root/arch/arm/mach-sa1100/neponset.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2016-08-31 08:49:53 +0100
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2022-04-02 11:11:35 +0100
commit414f65324bd9c73b9aa46ba67d368045889342b8 (patch)
tree06d8da8c37c7d9d4c74134fb66830fd9af360a4f /arch/arm/mach-sa1100/neponset.c
parentfc1a2725af8183079fe0b8c2f52fa5b478bfc431 (diff)
ARM: sa1100/neponset: add ethernet oscillator
Add the clock structure for the external SMC91x ethernet oscillator. This oscillator has an enable signal which allows the oscillator to be placed in low power mode when not required. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'arch/arm/mach-sa1100/neponset.c')
-rw-r--r--arch/arm/mach-sa1100/neponset.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 6876bc1e33b4..2b2fff442ba7 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -2,10 +2,13 @@
/*
* linux/arch/arm/mach-sa1100/neponset.c
*/
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/gpio-reg.h>
#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/irq.h>
@@ -79,6 +82,9 @@ struct neponset_drvdata {
struct platform_device *smc91x;
unsigned irq_base;
struct gpio_chip *gpio[4];
+ struct clk_hw *enet_osc_ck;
+ struct clk_hw *enet_osc_gate;
+ struct clk_lookup *enet_osc_cl;
};
static struct gpiod_lookup_table neponset_uart1_gpio_table = {
@@ -218,6 +224,38 @@ static int neponset_init_gpio(struct gpio_chip **gcp,
return 0;
}
+static int neponset_init_enet(struct device *dev, struct neponset_drvdata *d)
+{
+ struct gpio_desc *gpio;
+ int ret;
+
+ d->enet_osc_ck = clk_hw_register_fixed_rate(dev, "nep_enet_osc",
+ NULL, 0, 20000000);
+ if (IS_ERR(d->enet_osc_ck))
+ return PTR_ERR(d->enet_osc_ck);
+
+ gpio = gpio_to_desc(d->gpio[0]->base + 3);
+ d->enet_osc_gate = clk_hw_register_gpio_gate(dev, "nep_enet_gate",
+ "nep_enet_osc", gpio, 0);
+ if (IS_ERR(d->enet_osc_gate)) {
+ ret = PTR_ERR(d->enet_osc_gate);
+ goto err;
+ }
+
+ d->enet_osc_cl = clkdev_hw_create(d->enet_osc_gate, NULL, "smc91x.0");
+ if (!d->enet_osc_cl) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ if (d->enet_osc_ck)
+ clk_hw_unregister_fixed_rate(d->enet_osc_ck);
+ return ret;
+}
+
static struct sa1111_platform_data sa1111_info = {
.disable_devs = SA1111_DEVID_PS2_MSE,
};
@@ -337,6 +375,8 @@ static int neponset_probe(struct platform_device *dev)
gpiod_add_lookup_table(&neponset_uart3_gpio_table);
gpiod_add_lookup_table(&neponset_pcmcia_table);
+ neponset_init_enet(&dev->dev, d);
+
/*
* We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
* something on the Neponset activates this IRQ on sleep (eth?)
@@ -386,6 +426,9 @@ static int neponset_remove(struct platform_device *dev)
if (!IS_ERR(d->smc91x))
platform_device_unregister(d->smc91x);
+ clkdev_drop(d->enet_osc_cl);
+ clk_hw_unregister_fixed_rate(d->enet_osc_ck);
+
gpiod_remove_lookup_table(&neponset_pcmcia_table);
gpiod_remove_lookup_table(&neponset_uart3_gpio_table);
gpiod_remove_lookup_table(&neponset_uart1_gpio_table);