0
0
mirror of https://git.openwrt.org/openwrt/openwrt.git synced 2025-11-01 19:39:26 +00:00
Files
openwrt/target/linux/airoha/patches-6.12/600-01-clk-en7523-convert-driver-to-regmap-API.patch
Christian Marangi c5b12fc02a airoha: Introduce support for Airoha AN7583 SoC
Introduce initial support for Airoha AN7583 SoC and add all the required
patch for basic functionality of the SoC.

Airoha AN7583 is based on Airoha EN7581 SoC with some major changes on
the PHY handling and Serdes. It can be see as a lower spec of EN7581
with modern and simplified implementations.

All the patch are sent upstream and are pending revision. Support for
PCIe and USB will come later as soon as DT structure is accepted
upstream.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
2025-09-26 05:00:07 +02:00

352 lines
11 KiB
Diff

From 8d5a00b3b83f76d255bcffc91d5263f72b27547a Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 7 Feb 2025 23:51:23 +0100
Subject: [PATCH 01/10] clk: en7523: convert driver to regmap API
Convert driver to regmap API, in preparation for support of Airoha
AN7523 as the SCU will be an MFD and the regmap will be provided in the
parent node.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/clk-en7523.c | 137 ++++++++++++++++++++++-----------------
1 file changed, 76 insertions(+), 61 deletions(-)
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
@@ -34,6 +35,7 @@
#define REG_RESET_CONTROL_PCIE2 BIT(26)
/* EN7581 */
#define REG_NP_SCU_PCIC 0x88
+#define REG_PCIE_CTRL GENMASK(7, 0)
#define REG_NP_SCU_SSTR 0x9c
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
@@ -63,14 +65,14 @@ struct en_clk_desc {
};
struct en_clk_gate {
- void __iomem *base;
+ struct regmap *map;
struct clk_hw hw;
};
struct en_rst_data {
const u16 *bank_ofs;
const u16 *idx_map;
- void __iomem *base;
+ struct regmap *map;
struct reset_controller_dev rcdev;
};
@@ -388,44 +390,44 @@ static u32 en7523_get_div(const struct e
static int en7523_pci_is_enabled(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+ u32 val;
- return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1);
+ regmap_read(cg->map, REG_PCI_CONTROL, &val);
+ return !!(val & REG_PCI_CONTROL_REFCLK_EN1);
}
static int en7523_pci_prepare(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
- void __iomem *np_base = cg->base;
- u32 val, mask;
+ struct regmap *map = cg->map;
+ u32 mask;
/* Need to pull device low before reset */
- val = readl(np_base + REG_PCI_CONTROL);
- val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT);
- writel(val, np_base + REG_PCI_CONTROL);
+ regmap_clear_bits(map, REG_PCI_CONTROL,
+ REG_PCI_CONTROL_PERSTOUT1 |
+ REG_PCI_CONTROL_PERSTOUT);
usleep_range(1000, 2000);
/* Enable PCIe port 1 */
- val |= REG_PCI_CONTROL_REFCLK_EN1;
- writel(val, np_base + REG_PCI_CONTROL);
+ regmap_set_bits(map, REG_PCI_CONTROL,
+ REG_PCI_CONTROL_REFCLK_EN1);
usleep_range(1000, 2000);
/* Reset to default */
- val = readl(np_base + REG_RESET_CONTROL1);
mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
REG_RESET_CONTROL_PCIEHB;
- writel(val & ~mask, np_base + REG_RESET_CONTROL1);
+ regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
usleep_range(1000, 2000);
- writel(val | mask, np_base + REG_RESET_CONTROL1);
+ regmap_set_bits(map, REG_RESET_CONTROL1, mask);
msleep(100);
- writel(val & ~mask, np_base + REG_RESET_CONTROL1);
+ regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
usleep_range(5000, 10000);
/* Release device */
mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT;
- val = readl(np_base + REG_PCI_CONTROL);
- writel(val & ~mask, np_base + REG_PCI_CONTROL);
+ regmap_clear_bits(map, REG_PCI_CONTROL, mask);
usleep_range(1000, 2000);
- writel(val | mask, np_base + REG_PCI_CONTROL);
+ regmap_set_bits(map, REG_PCI_CONTROL, mask);
msleep(250);
return 0;
@@ -434,16 +436,13 @@ static int en7523_pci_prepare(struct clk
static void en7523_pci_unprepare(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
- void __iomem *np_base = cg->base;
- u32 val;
+ struct regmap *map = cg->map;
- val = readl(np_base + REG_PCI_CONTROL);
- val &= ~REG_PCI_CONTROL_REFCLK_EN1;
- writel(val, np_base + REG_PCI_CONTROL);
+ regmap_clear_bits(map, REG_PCI_CONTROL, REG_PCI_CONTROL_REFCLK_EN1);
}
static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
- void __iomem *np_base)
+ struct regmap *clk_map)
{
const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
struct clk_init_data init = {
@@ -456,7 +455,7 @@ static struct clk_hw *en7523_register_pc
if (!cg)
return NULL;
- cg->base = np_base;
+ cg->map = clk_map;
cg->hw.init = &init;
if (init.ops->unprepare)
@@ -474,21 +473,20 @@ static int en7581_pci_is_enabled(struct
u32 val, mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
- val = readl(cg->base + REG_PCI_CONTROL);
+ regmap_read(cg->map, REG_PCI_CONTROL, &val);
return (val & mask) == mask;
}
static int en7581_pci_enable(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
- void __iomem *np_base = cg->base;
- u32 val, mask;
+ struct regmap *map = cg->map;
+ u32 mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
REG_PCI_CONTROL_PERSTOUT;
- val = readl(np_base + REG_PCI_CONTROL);
- writel(val | mask, np_base + REG_PCI_CONTROL);
+ regmap_set_bits(map, REG_PCI_CONTROL, mask);
return 0;
}
@@ -496,19 +494,18 @@ static int en7581_pci_enable(struct clk_
static void en7581_pci_disable(struct clk_hw *hw)
{
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
- void __iomem *np_base = cg->base;
- u32 val, mask;
+ struct regmap *map = cg->map;
+ u32 mask;
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
REG_PCI_CONTROL_PERSTOUT;
- val = readl(np_base + REG_PCI_CONTROL);
- writel(val & ~mask, np_base + REG_PCI_CONTROL);
+ regmap_clear_bits(map, REG_PCI_CONTROL, mask);
usleep_range(1000, 2000);
}
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
- void __iomem *base, void __iomem *np_base)
+ struct regmap *map, struct regmap *clk_map)
{
struct clk_hw *hw;
u32 rate;
@@ -517,10 +514,12 @@ static void en7523_register_clocks(struc
for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
const struct en_clk_desc *desc = &en7523_base_clks[i];
u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
- u32 val = readl(base + desc->base_reg);
+ u32 val;
+
+ regmap_read(map, desc->base_reg, &val);
rate = en7523_get_base_rate(desc, val);
- val = readl(base + reg);
+ regmap_read(map, reg, &val);
rate /= en7523_get_div(desc, val);
hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
@@ -533,30 +532,47 @@ static void en7523_register_clocks(struc
clk_data->hws[desc->id] = hw;
}
- hw = en7523_register_pcie_clk(dev, np_base);
+ hw = en7523_register_pcie_clk(dev, clk_map);
clk_data->hws[EN7523_CLK_PCIE] = hw;
}
+static const struct regmap_config en7523_clk_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
static int en7523_clk_hw_init(struct platform_device *pdev,
struct clk_hw_onecell_data *clk_data)
{
void __iomem *base, *np_base;
+ struct regmap *map, *clk_map;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
+ map = devm_regmap_init_mmio(&pdev->dev, base,
+ &en7523_clk_regmap_config);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
np_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(np_base))
return PTR_ERR(np_base);
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
+ clk_map = devm_regmap_init_mmio(&pdev->dev, np_base,
+ &en7523_clk_regmap_config);
+ if (IS_ERR(clk_map))
+ return PTR_ERR(clk_map);
+
+ en7523_register_clocks(&pdev->dev, clk_data, map, clk_map);
return 0;
}
static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
- struct regmap *map, void __iomem *base)
+ struct regmap *map, struct regmap *clk_map)
{
struct clk_hw *hw;
u32 rate;
@@ -593,7 +609,7 @@ static void en7581_register_clocks(struc
clk_data->hws[desc->id] = hw;
}
- hw = en7523_register_pcie_clk(dev, base);
+ hw = en7523_register_pcie_clk(dev, clk_map);
clk_data->hws[EN7523_CLK_PCIE] = hw;
}
@@ -601,15 +617,10 @@ static int en7523_reset_update(struct re
unsigned long id, bool assert)
{
struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
- void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
- u32 val;
+ u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
- val = readl(addr);
- if (assert)
- val |= BIT(id % RST_NR_PER_BANK);
- else
- val &= ~BIT(id % RST_NR_PER_BANK);
- writel(val, addr);
+ regmap_update_bits(rst_data->map, addr, BIT(id % RST_NR_PER_BANK),
+ assert ? BIT(id % RST_NR_PER_BANK) : 0);
return 0;
}
@@ -630,9 +641,11 @@ static int en7523_reset_status(struct re
unsigned long id)
{
struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
- void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
+ u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
+ u32 val;
- return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
+ regmap_read(rst_data->map, addr, &val);
+ return !!(val & BIT(id % RST_NR_PER_BANK));
}
static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
@@ -652,7 +665,7 @@ static const struct reset_control_ops en
.status = en7523_reset_status,
};
-static int en7581_reset_register(struct device *dev, void __iomem *base)
+static int en7581_reset_register(struct device *dev, struct regmap *map)
{
struct en_rst_data *rst_data;
@@ -662,7 +675,7 @@ static int en7581_reset_register(struct
rst_data->bank_ofs = en7581_rst_ofs;
rst_data->idx_map = en7581_rst_map;
- rst_data->base = base;
+ rst_data->map = map;
rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
rst_data->rcdev.of_xlate = en7523_reset_xlate;
@@ -678,9 +691,8 @@ static int en7581_reset_register(struct
static int en7581_clk_hw_init(struct platform_device *pdev,
struct clk_hw_onecell_data *clk_data)
{
- struct regmap *map;
+ struct regmap *map, *clk_map;
void __iomem *base;
- u32 val;
map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
if (IS_ERR(map))
@@ -690,15 +702,18 @@ static int en7581_clk_hw_init(struct pla
if (IS_ERR(base))
return PTR_ERR(base);
- en7581_register_clocks(&pdev->dev, clk_data, map, base);
-
- val = readl(base + REG_NP_SCU_SSTR);
- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
- writel(val, base + REG_NP_SCU_SSTR);
- val = readl(base + REG_NP_SCU_PCIC);
- writel(val | 3, base + REG_NP_SCU_PCIC);
+ clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config);
+ if (IS_ERR(clk_map))
+ return PTR_ERR(clk_map);
+
+ en7581_register_clocks(&pdev->dev, clk_data, map, clk_map);
+
+ regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
+ REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+ regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL,
+ FIELD_PREP(REG_PCIE_CTRL, 3));
- return en7581_reset_register(&pdev->dev, base);
+ return en7581_reset_register(&pdev->dev, clk_map);
}
static int en7523_clk_probe(struct platform_device *pdev)