Skip to contentSkip to conversation

clk: Add driver for MAX9485

PATCH Applied Daniel Mack 2 participants 5 messages Jul 6, 2018 Common clk

lore
Share & tools
lore
#0 lore raw

v5 cover clk: Add driver for MAX9485

This is v5 of the driver for Maxim's MAX9485 programmable audio clock generator.

v4 → v5:
* Removed license boilerplate as we have an SPDX header
* Moved initial register read from recalc_rate() to probe()
* Changed Kconfig prompt text
* Dropped patch to add binding as it has already been applied

v3 → v4:
* Rebased to 4.18-rc1

v2 → v3:

* Addressed a lot of issues pointed out by Stephen Boyd:
* Dropped local register caching
* Implement own OF clk_hw getter in favor of the onecell helper
* Implemented recalc_rate() properly by reading from the hardware
* Dropped input clock frequency validation
* Style issues

* Fixed a gpio line handling bug in resume
* Added Rob's Revied-by to 1/2

v1 → v2:

* Now served as two patches, one for the DT bits, and one for the actual implementation. The DT bits are put in the 1st patch because the implementation depends on the shared header file.

* Added support for suspend/resume

Daniel Mack (1):
clk: Add driver for MAX9485

 drivers/clk/Kconfig       |   6 +
 drivers/clk/Makefile      |   1 +
 drivers/clk/clk-max9485.c | 385 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 392 insertions(+)
 create mode 100644 drivers/clk/clk-max9485.c
Signature · 1 line
2.17.1
#1 lore raw

PATCH v5 1/1 clk: Add driver for MAX9485

This patch adds a driver for MAX9485, a programmable audio clock generator.

The device requires a 27.000 MHz clock input. It can provide a gated buffered output of its input clock and two gated outputs of a PLL that can generate one out of 16 discrete frequencies. There is only one PLL however, so the two gated outputs will always have the same frequency but they can be switched individually.

The driver for this device exposes 4 clocks in total:

- MAX9485_MCLKOUT: A gated, buffered output of the input clock
- MAX9485_CLKOUT: A PLL that can be configured to 16 different
discrete frequencies
- MAX9485_CLKOUT[1,2]: Two gated outputs for MAX9485_CLKOUT

Some PLL output frequencies can be achieved with different register settings. The driver will select the one with lowest jitter in such cases.

---
 drivers/clk/Kconfig       |   6 +
 drivers/clk/Makefile      |   1 +
 drivers/clk/clk-max9485.c | 385 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 392 insertions(+)
 create mode 100644 drivers/clk/clk-max9485.c
drivers/clk/Kconfig +6 -0
index 721572a8c429..3e846d22d2e0 100644
@@ -45,6 +45,12 @@ config COMMON_CLK_MAX77686
 	  This driver supports Maxim 77620/77686/77802 crystal oscillator
 	  clock.
 
+config COMMON_CLK_MAX9485
+	tristate "Maxim 9485 Programmable Clock Generator"
+	depends on I2C
+	---help---
+	  This driver supports Maxim 9485 Programmable Audio Clock Generator
+
 config COMMON_CLK_RK808
 	tristate "Clock driver for RK805/RK808/RK818"
 	depends on MFD_RK808
drivers/clk/Makefile +1 -0
index ae40cbe770f0..24fc2b634362 100644
@@ -31,6 +31,7 @@ obj-$(CONFIG_COMMON_CLK_ASPEED)		+= clk-aspeed.o
 obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
 obj-$(CONFIG_CLK_HSDK)			+= clk-hsdk-pll.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
+obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NPCM7XX)	    	+= clk-npcm7xx.o
drivers/clk/clk-max9485.c new file +385 -0

385 lines not on this page · raw message

Signature · 1 line
2.17.1
maintainer Applied
#2 lore raw

Quoting Daniel Mack (2018-07-06 11:53:03)

Quoted 1 line

This patch adds a driver for MAX9485, a programmable audio clock generato=

r.

Quoted 5 lines

=

The device requires a 27.000 MHz clock input. It can provide a gated buffered output of its input clock and two gated outputs of a PLL that can generate one out of 16 discrete frequencies. There is only one PLL howeve=

r,

Quoted 13 lines

so the two gated outputs will always have the same frequency but they can be switched individually.
=

The driver for this device exposes 4 clocks in total:
=

- MAX9485_MCLKOUT: A gated, buffered output of the input clock
- MAX9485_CLKOUT: A PLL that can be configured to 16 different
discrete frequencies
- MAX9485_CLKOUT[1,2]: Two gated outputs for MAX9485_CLKOUT =

Quoted 6 lines

Some PLL output frequencies can be achieved with different register settings. The driver will select the one with lowest jitter in such cases. =

---

Applied to clk-next

maintainer
#3 lore raw
In reply to Daniel Mack

Quoting Daniel Mack (2018-07-06 11:53:03)

Quoted 1 line

This patch adds a driver for MAX9485, a programmable audio clock generato=

r.

Quoted 5 lines

=

The device requires a 27.000 MHz clock input. It can provide a gated buffered output of its input clock and two gated outputs of a PLL that can generate one out of 16 discrete frequencies. There is only one PLL howeve=

r,

Quoted 13 lines

so the two gated outputs will always have the same frequency but they can be switched individually.
=

The driver for this device exposes 4 clocks in total:
=

- MAX9485_MCLKOUT: A gated, buffered output of the input clock
- MAX9485_CLKOUT: A PLL that can be configured to 16 different
discrete frequencies
- MAX9485_CLKOUT[1,2]: Two gated outputs for MAX9485_CLKOUT =

Quoted 6 lines

Some PLL output frequencies can be achieved with different register settings. The driver will select the one with lowest jitter in such cases. =

---

BTW, I squashed in this to make things a little cleaner:

---8<----

drivers/clk/clk-max9485.c +0 -0
index ae9d3c20a513..5e80f3d090f3 100644
@@ -149,10 +149,11 @@ static unsigned long max9485_clkout_recalc_rate(struc=

t clk_hw *hw,
{
struct max9485_clk_hw *clk_hw =3D to_max9485_clk(hw); struct max9485_driver_data *drvdata =3D clk_hw->drvdata;
+ u8 val =3D drvdata->reg_value & MAX9485_FREQ_MASK;
const struct max9485_rate *entry;
=

for (entry =3D max9485_rates; entry->out !=3D 0; entry++)
- if ((drvdata->reg_value & MAX9485_FREQ_MASK) =3D=3D entry->reg_value)
+ if (val =3D=3D entry->reg_value)
return entry->out;
=

return 0;
@@ -244,7 +245,8 @@ static const struct max9485_clk max9485_clks[MAX9485_NU= M_CLKS] =3D {
},
};
=

-static struct clk_hw *max9485_of_clk_get(struct of_phandle_args *clkspec, = void *data)
+static struct clk_hw *
+max9485_of_clk_get(struct of_phandle_args *clkspec, void *data)
{
struct max9485_driver_data *drvdata =3D data;
unsigned int idx =3D clkspec->args[0];

#4 lore raw
Quoted 44 lines · Stephen Boyd

Quoting Daniel Mack (2018-07-06 11:53:03)

Quoted 15 lines

This patch adds a driver for MAX9485, a programmable audio clock generator.

The device requires a 27.000 MHz clock input. It can provide a gated buffered output of its input clock and two gated outputs of a PLL that can generate one out of 16 discrete frequencies. There is only one PLL however, so the two gated outputs will always have the same frequency but they can be switched individually.

The driver for this device exposes 4 clocks in total:

- MAX9485_MCLKOUT: A gated, buffered output of the input clock
- MAX9485_CLKOUT: A PLL that can be configured to 16 different
discrete frequencies
- MAX9485_CLKOUT[1,2]: Two gated outputs for MAX9485_CLKOUT

Quoted 5 lines

Some PLL output frequencies can be achieved with different register settings. The driver will select the one with lowest jitter in such cases.

---

BTW, I squashed in this to make things a little cleaner:

---8<----

drivers/clk/clk-max9485.c +2 -1
index ae9d3c20a513..5e80f3d090f3 100644
@@ -149,10 +149,11 @@ static unsigned long max9485_clkout_recalc_rate(struct clk_hw *hw,
 {
 	struct max9485_clk_hw *clk_hw = to_max9485_clk(hw);
 	struct max9485_driver_data *drvdata = clk_hw->drvdata;
+	u8 val = drvdata->reg_value & MAX9485_FREQ_MASK;
 	const struct max9485_rate *entry;
 
 	for (entry = max9485_rates; entry->out != 0; entry++)
-		if ((drvdata->reg_value & MAX9485_FREQ_MASK) == entry->reg_value)
+		if (val == entry->reg_value)
 			return entry->out;
 
 	return 0;

drivers/clk/clk-max9485.c static const struct max9485_clk max9485_clks[MAX9485_NUM_CLKS] = { · line 252

Quoted 9 lines
drivers/clk/clk-max9485.c +2 -1
@@ -244,7 +245,8 @@ static const struct max9485_clk max9485_clks[MAX9485_NUM_CLKS] = {
 	},
 };
 
-static struct clk_hw *max9485_of_clk_get(struct of_phandle_args *clkspec, void *data)
+static struct clk_hw *
+max9485_of_clk_get(struct of_phandle_args *clkspec, void *data)
 {
 	struct max9485_driver_data *drvdata = data;
 	unsigned int idx = clkspec->args[0];

Sure, that's fine.

Thanks,
Daniel