Commit 9d0af685 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'clk-microchip-6.13' of...

Merge tag 'clk-microchip-6.13' of https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux into clk-microchip

Pull Microchip clk driver updates from Claudiu Beznea:

 - Support for the Microchip LAN969X SoC

* tag 'clk-microchip-6.13' of https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux:
  clk: lan966x: add support for lan969x SoC clock driver
  clk: lan966x: prepare driver for lan969x support
  clk: lan966x: make clk_names const char * const
  dt-bindings: clock: add support for lan969x
parents 9852d85e 47d072b1
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -16,7 +16,18 @@ description: |

properties:
  compatible:
    const: microchip,lan966x-gck
    oneOf:
      - enum:
          - microchip,lan966x-gck
          - microchip,lan9691-gck
      - items:
          - enum:
              - microchip,lan9698-gck
              - microchip,lan9696-gck
              - microchip,lan9694-gck
              - microchip,lan9693-gck
              - microchip,lan9692-gck
          - const: microchip,lan9691-gck

  reg:
    minItems: 1
+62 −16
Original line number Diff line number Diff line
@@ -24,13 +24,20 @@

#define DIV_MAX		255

static const char *clk_names[N_CLOCKS] = {
static const char * const lan966x_clk_names[] = {
	"qspi0", "qspi1", "qspi2", "sdmmc0",
	"pi", "mcan0", "mcan1", "flexcom0",
	"flexcom1", "flexcom2", "flexcom3",
	"flexcom4", "timer1", "usb_refclk",
};

static const char * const lan969x_clk_names[] = {
	"qspi0", "qspi2", "sdmmc0", "sdmmc1",
	"mcan0", "mcan1", "flexcom0",
	"flexcom1", "flexcom2", "flexcom3",
	"timer1", "usb_refclk",
};

struct lan966x_gck {
	struct clk_hw hw;
	void __iomem *reg;
@@ -53,7 +60,7 @@ struct clk_gate_soc_desc {
	int bit_idx;
};

static const struct clk_gate_soc_desc clk_gate_desc[] = {
static const struct clk_gate_soc_desc lan966x_clk_gate_desc[] = {
	{ "uhphs", 11 },
	{ "udphs", 10 },
	{ "mcramc", 9 },
@@ -61,6 +68,37 @@ static const struct clk_gate_soc_desc clk_gate_desc[] = {
	{ }
};

static const struct clk_gate_soc_desc lan969x_clk_gate_desc[] = {
	{ "usb_drd", 10 },
	{ "mcramc", 9 },
	{ "hmatrix", 8 },
	{ }
};

struct lan966x_match_data {
	char *name;
	const char * const *clk_name;
	const struct clk_gate_soc_desc *clk_gate_desc;
	u8 num_generic_clks;
	u8 num_total_clks;
};

static struct lan966x_match_data lan966x_desc = {
	.name = "lan966x",
	.clk_name = lan966x_clk_names,
	.clk_gate_desc = lan966x_clk_gate_desc,
	.num_total_clks = 18,
	.num_generic_clks = 14,
};

static struct lan966x_match_data lan969x_desc = {
	.name = "lan969x",
	.clk_name = lan969x_clk_names,
	.clk_gate_desc = lan969x_clk_gate_desc,
	.num_total_clks = 15,
	.num_generic_clks = 12,
};

static DEFINE_SPINLOCK(clk_gate_lock);
static void __iomem *base;

@@ -186,24 +224,26 @@ static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i)
};

static int lan966x_gate_clk_register(struct device *dev,
				     const struct lan966x_match_data *data,
				     struct clk_hw_onecell_data *hw_data,
				     void __iomem *gate_base)
{
	int i;
	for (int i = data->num_generic_clks; i < data->num_total_clks; ++i) {
		int idx = i - data->num_generic_clks;
		const struct clk_gate_soc_desc *desc;

	for (i = GCK_GATE_UHPHS; i < N_CLOCKS; ++i) {
		int idx = i - GCK_GATE_UHPHS;
		desc = &data->clk_gate_desc[idx];

		hw_data->hws[i] =
			devm_clk_hw_register_gate(dev, clk_gate_desc[idx].name,
						  "lan966x", 0, gate_base,
						  clk_gate_desc[idx].bit_idx,
			devm_clk_hw_register_gate(dev, desc->name,
						  data->name, 0, gate_base,
						  desc->bit_idx,
						  0, &clk_gate_lock);

		if (IS_ERR(hw_data->hws[i]))
			return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]),
					     "failed to register %s clock\n",
					     clk_gate_desc[idx].name);
					     desc->name);
	}

	return 0;
@@ -211,13 +251,18 @@ static int lan966x_gate_clk_register(struct device *dev,

static int lan966x_clk_probe(struct platform_device *pdev)
{
	const struct lan966x_match_data *data;
	struct clk_hw_onecell_data *hw_data;
	struct device *dev = &pdev->dev;
	void __iomem *gate_base;
	struct resource *res;
	int i, ret;

	hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, N_CLOCKS),
	data = device_get_match_data(dev);
	if (!data)
		return -EINVAL;

	hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, data->num_total_clks),
			       GFP_KERNEL);
	if (!hw_data)
		return -ENOMEM;
@@ -228,10 +273,10 @@ static int lan966x_clk_probe(struct platform_device *pdev)

	init.ops = &lan966x_gck_ops;

	hw_data->num = GCK_GATE_UHPHS;
	hw_data->num = data->num_generic_clks;

	for (i = 0; i < GCK_GATE_UHPHS; i++) {
		init.name = clk_names[i];
	for (i = 0; i < data->num_generic_clks; i++) {
		init.name = data->clk_name[i];
		hw_data->hws[i] = lan966x_gck_clk_register(dev, i);
		if (IS_ERR(hw_data->hws[i])) {
			dev_err(dev, "failed to register %s clock\n",
@@ -246,9 +291,9 @@ static int lan966x_clk_probe(struct platform_device *pdev)
		if (IS_ERR(gate_base))
			return PTR_ERR(gate_base);

		hw_data->num = N_CLOCKS;
		hw_data->num = data->num_total_clks;

		ret = lan966x_gate_clk_register(dev, hw_data, gate_base);
		ret = lan966x_gate_clk_register(dev, data, hw_data, gate_base);
		if (ret)
			return ret;
	}
@@ -257,7 +302,8 @@ static int lan966x_clk_probe(struct platform_device *pdev)
}

static const struct of_device_id lan966x_clk_dt_ids[] = {
	{ .compatible = "microchip,lan966x-gck", },
	{ .compatible = "microchip,lan966x-gck", .data = &lan966x_desc },
	{ .compatible = "microchip,lan9691-gck", .data = &lan969x_desc },
	{ }
};
MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids);