Re: [PATCH v3 1/9] dt-bindings: memory: Document RZ/G3E support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Geert,

On Mon, Mar 31, 2025 at 7:25 PM Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote:
>
> Hi Biju,
>
> On Mon, 31 Mar 2025 at 17:33, Biju Das <biju.das.jz@xxxxxxxxxxxxxx> wrote:
> > > From: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx>
> > > On Mon, 31 Mar 2025 at 16:34, Biju Das <biju.das.jz@xxxxxxxxxxxxxx> wrote:
> > > > > From: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> On Mon, 31 Mar 2025
> > > > > at 15:54, Biju Das <biju.das.jz@xxxxxxxxxxxxxx> wrote:
> > > > > > > From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx> Document support for
> > > > > > > the Expanded Serial Peripheral Interface (xSPI) Controller in
> > > > > > > the Renesas RZ/G3E
> > > > > > > (R9A09G047) SoC.
> > > > > > >
> > > > > > > Reviewed-by: Rob Herring (Arm) <robh@xxxxxxxxxx>
> > > > > > > Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
> > > > >
> > > > > > > --- /dev/null
> > > > > > > +++ b/Documentation/devicetree/bindings/memory-controllers/renes
> > > > > > > +++ as,r
> > > > > > > +++ zg3e
> > > > > > > +++ -xspi.yaml
> > > > >
> > > > > > > +    spi@11030000 {
> > > > > > > +        compatible = "renesas,r9a09g047-xspi";
> > > > > > > +        reg = <0x11030000 0x10000>, <0x20000000 0x10000000>;
> > > > > > > +        reg-names = "regs", "dirmap";
> > > > > > > +        interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
> > > > > > > +                     <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>;
> > > > > > > +        interrupt-names = "pulse", "err_pulse";
> > > > > > > +        clocks = <&cpg CPG_MOD 0x9f>, <&cpg CPG_MOD 0xa0>,
> > > > > > > +                 <&cpg CPG_MOD 0xa1>, <&cpg CPG_MOD 0xa1>;
> > > > > >
> > > > > > On the next version I am going to update spix2 clk as <&cpg
> > > > > > CPG_CORE R9A09G047_SPI_CLK_SPIX2>
>
> According to the RZ/G3E clock system diagram, (the parent of) clk_spi
> is derived from (the parent of) clk_spix2, not the other way around?
> So you can model clk_spi as a fixed divider clock with parent clk_spix2
> and factor two.  I.e. provide a new core clock R9A09G047_SPI_CLK_SPI
> instead of your proposed R9A09G047_SPI_CLK_SPIX2?
>
With this approach when R9A09G047_SPI_CLK_SPI is used as a core clock
and XSPI node is disabled the clk_summary reports the core clock is ON
(while it's actually OFF).

root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi
          .smux2_xspi_clk1           0       0        0
320000000   0          0     50000      Y            deviceless
              no_connection_id
             .pllcm33_xspi           0       0        0
40000000    0          0     50000      Y               deviceless
                 no_connection_id
                spi_clk_spix2        0       0        0
40000000    0          0     50000      N                  deviceless
                    no_connection_id
                spi_clk_spi          0       0        0
20000000    0          0     50000      Y                  deviceless
                    no_connection_id
             spi_aclk                0       0        0
200000000   0          0     50000      N               deviceless
                 no_connection_id
             spi_hclk                0       0        0
200000000   0          0     50000      N               deviceless
                 no_connection_id
          .smux2_xspi_clk0           0       0        0
533333333   0          0     50000      Y            deviceless
              no_connection_id

Can we maybe use a unused ON index and ON bit for example 25, 0 (ie
0x190) and represent this is a module clock for example for the
spi_clk_spix2 clock and use this in the DT and let the CPG core code
handle such turning ON/OF the module clocks based on the enable count
which will be handled internally in the driver?

I have some POC code for the paired clocks which will handle the
enable count of the paired module clocks, below is the diff. Please
share your thoughts.

diff --git a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
index 3c5984ee27ca..8a8f59ffdb4c 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
@@ -290,10 +290,10 @@ xspi: spi@11030000 {
                        interrupt-names = "pulse", "err_pulse";
                        clocks = <&cpg CPG_MOD 0x9f>,
                                 <&cpg CPG_MOD 0xa0>,
-                                <&cpg CPG_CORE R9A09G057_SPI_CLK_SPI>,
-                                <&cpg CPG_MOD 0xa1>;
+                                <&cpg CPG_MOD 0xa1>,
+                                <&cpg CPG_MOD 0x190>;
                        clock-names = "ahb", "axi", "spi", "spix2";
-                       assigned-clocks = <&cpg CPG_CORE R9A09G057_SPI_CLK_SPI>;
+                       assigned-clocks = <&cpg CPG_MOD 0xa1>;
                        assigned-clock-rates = <133333334>;
                        resets = <&cpg 0xa3>, <&cpg 0xa4>;
                        reset-names = "hresetn", "aresetn";
diff --git a/drivers/clk/renesas/r9a09g057-cpg.c
b/drivers/clk/renesas/r9a09g057-cpg.c
index 9952474bcf48..d5eef17ad5fc 100644
--- a/drivers/clk/renesas/r9a09g057-cpg.c
+++ b/drivers/clk/renesas/r9a09g057-cpg.c
@@ -43,6 +43,7 @@ enum clk_ids {
        CLK_SMUX2_XSPI_CLK0,
        CLK_SMUX2_XSPI_CLK1,
        CLK_PLLCM33_XSPI,
+       CLK_PLLCM33_XSPIX2,
        CLK_PLLCLN_DIV2,
        CLK_PLLCLN_DIV8,
        CLK_PLLCLN_DIV16,
@@ -176,6 +177,7 @@ static const struct cpg_core_clk
r9a09g057_core_clks[] __initconst = {
        DEF_SMUX(".smux2_xspi_clk1", CLK_SMUX2_XSPI_CLK1,
SSEL1_SELCTL3, smux2_xspi_clk1),
        DEF_CSDIV(".pllcm33_xspi", CLK_PLLCM33_XSPI,
CLK_SMUX2_XSPI_CLK1, CSDIV0_DIVCTL3,
                  dtable_2_16),
+       DEF_FIXED(".pllcm33_xspix2", CLK_PLLCM33_XSPIX2,
CLK_PLLCM33_XSPI, 2, 1),

        DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
        DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
@@ -231,7 +233,6 @@ static const struct cpg_core_clk
r9a09g057_core_clks[] __initconst = {
                  CLK_PLLETH_DIV_125_FIX, 1, 1),
        DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G057_GBETH_1_CLK_PTP_REF_I,
                  CLK_PLLETH_DIV_125_FIX, 1, 1),
-       DEF_FIXED("spi_clk_spi", R9A09G057_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2),
 };

 static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
@@ -311,8 +312,10 @@ static const struct rzv2h_mod_clk
r9a09g057_mod_clks[] __initconst = {
                                                BUS_MSTOP(4, BIT(5))),
        DEF_MOD("spi_aclk",                     CLK_PLLCM33_GEAR, 10, 0, 5, 0,
                                                BUS_MSTOP(4, BIT(5))),
-       DEF_MOD_NO_PM("spi_clk_spix2",          CLK_PLLCM33_XSPI, 10, 1, 5, 2,
+       DEF_MOD_PAIRED("spi_clk_spi",           CLK_PLLCM33_XSPI, 10, 1, 5, 1,
                                                BUS_MSTOP(4, BIT(5))),
+       DEF_MOD_PAIRED_ALIAS("spi_clk_spix2",   CLK_PLLCM33_XSPIX2, 25, 0, 5, 2,
+                                               BUS_MSTOP(4, BIT(5)), 10, 1),
        DEF_MOD("sdhi_0_imclk",                 CLK_PLLCLN_DIV8, 10, 3, 5, 3,
                                                BUS_MSTOP(8, BIT(2))),
        DEF_MOD("sdhi_0_imclk2",                CLK_PLLCLN_DIV8, 10, 4, 5, 4,
@@ -508,7 +511,7 @@ const struct rzv2h_cpg_info r9a09g057_cpg_info
__initconst = {
        /* Module Clocks */
        .mod_clks = r9a09g057_mod_clks,
        .num_mod_clks = ARRAY_SIZE(r9a09g057_mod_clks),
-       .num_hw_mod_clks = 25 * 16,
+       .num_hw_mod_clks = 26 * 16,

        /* Resets */
        .resets = r9a09g057_resets,
diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c
index 97bcd252fcbf..847ea71df865 100644
--- a/drivers/clk/renesas/rzv2h-cpg.c
+++ b/drivers/clk/renesas/rzv2h-cpg.c
@@ -71,6 +71,12 @@

 #define CPG_CLKSTATUS0         (0x700)

+struct rzv2h_paired_clock {
+       u8 on_index;
+       u8 on_bit;
+       unsigned int enabled_count;
+};
+
 /**
  * struct rzv2h_cpg_priv - Clock Pulse Generator Private Data
  *
@@ -87,6 +93,8 @@
  * @rcdev: Reset controller entity
  * @dsi_limits: PLL DSI parameters limits
  * @plldsi_div_parameters: PLL DSI and divider parameters configuration
+ * @pair_clks: Array of paired clocks
+ * @num_pair_clks: Number of paired clocks in pair_clks[]
  */
 struct rzv2h_cpg_priv {
        struct device *dev;
@@ -102,6 +110,9 @@ struct rzv2h_cpg_priv {

        atomic_t *mstop_count;

+       struct rzv2h_paired_clock *pair_clks;
+       unsigned int num_pair_clks;
+
        struct reset_controller_dev rcdev;

        const struct rzv2h_pll_div_limits *dsi_limits;
@@ -131,6 +142,11 @@ struct pll_clk {
  * @mon_index: monitor register offset
  * @mon_bit: monitor bit
  * @ext_clk_mux_index: mux index for external clock source, or -1 if internal
+ * @paired: indicates if this clock is paired with another clock ie it shares
+ *          the same ON bit and has a separate MON bit.
+ * @alias: indicates if this clock is paired and has been given dummy ON bit
+ * @pair_clk: pointer to paired clock structure if this clock is paired,
+ *           otherwise NULL.
  */
 struct mod_clock {
        struct rzv2h_cpg_priv *priv;
@@ -142,6 +158,9 @@ struct mod_clock {
        s8 mon_index;
        u8 mon_bit;
        s8 ext_clk_mux_index;
+       bool paired;
+       bool alias;
+       struct rzv2h_paired_clock *pair_clk;
 };

 #define to_mod_clock(_hw) container_of(_hw, struct mod_clock, hw)
@@ -853,8 +872,13 @@ static int rzv2h_mod_clock_is_enabled(struct clk_hw *hw)
                        return 0;
        }

-       offset = GET_CLK_ON_OFFSET(clock->on_index);
-       bitmask = BIT(clock->on_bit);
+       if (clock->alias) {
+               offset = GET_CLK_ON_OFFSET(clock->pair_clk->on_index);
+               bitmask = BIT(clock->pair_clk->on_bit);
+       } else {
+               offset = GET_CLK_ON_OFFSET(clock->on_index);
+               bitmask = BIT(clock->on_bit);
+       }

        return readl(priv->base + offset) & bitmask;
 }
@@ -870,24 +894,57 @@ static int rzv2h_mod_clock_endisable(struct
clk_hw *hw, bool enable)
        u32 value;
        int error;

-       dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", reg, hw->clk,
-               str_on_off(enable));
+       if (clock->alias) {
+               reg = GET_CLK_ON_OFFSET(clock->pair_clk->on_index);
+               bitmask = BIT(clock->pair_clk->on_bit);
+       }

-       if (enabled == enable)
+       if (clock->paired)
+               dev_err(dev, "CLK_ON 0x%x/%pC %s\n", reg, hw->clk,
+                       str_on_off(enable));
+
+       if (enabled == enable) {
+               if (clock->paired && enable && clock->pair_clk->enabled_count) {
+                       clock->pair_clk->enabled_count++;
+                       dev_err(dev, "1: CLK_ON 0x%x/%pC %s cnt:%u\n",
+                               reg, hw->clk, str_on_off(enable),
+                               clock->pair_clk->enabled_count);
+               }
                return 0;
+       }

        value = bitmask << 16;
        if (enable) {
+               if (clock->paired && clock->pair_clk->enabled_count) {
+                       clock->pair_clk->enabled_count++;
+                       dev_err(dev, "2: CLK_ON 0x%x/%pC %s cnt:%u\n",
+                               reg, hw->clk, str_on_off(enable),
+                               clock->pair_clk->enabled_count);
+                       goto check_mon;
+               }
                value |= bitmask;
                writel(value, priv->base + reg);
                if (clock->mstop_data != BUS_MSTOP_NONE)
                        rzv2h_mod_clock_mstop_enable(priv, clock->mstop_data);
+               if (clock->paired)
+                       clock->pair_clk->enabled_count++;
        } else {
+               if (clock->paired) {
+                       if (clock->pair_clk->enabled_count)
+                               clock->pair_clk->enabled_count--;
+                       dev_err(dev, "3: CLK_ON 0x%x/%pC %s cnt:%u\n",
+                               reg, hw->clk, str_on_off(enable),
+                               clock->pair_clk->enabled_count);
+                       if (clock->pair_clk->enabled_count > 0)
+                               goto check_mon;
+               }
+
                if (clock->mstop_data != BUS_MSTOP_NONE)
                        rzv2h_mod_clock_mstop_disable(priv, clock->mstop_data);
                writel(value, priv->base + reg);
        }

+check_mon:
        if (!enable || clock->mon_index < 0)
                return 0;

@@ -918,6 +975,55 @@ static const struct clk_ops rzv2h_mod_clock_ops = {
        .is_enabled = rzv2h_mod_clock_is_enabled,
 };

+static int rzv2h_mod_clk_get_paired_cfg(struct rzv2h_cpg_priv *priv,
+                                       struct mod_clock *clock,
+                                       const struct rzv2h_mod_clk *mod)
+{
+       unsigned int i;
+       u8 on_index;
+       u8 on_bit;
+
+
+       if (!clock->paired)
+               return 0;
+
+       /* Get the paired clock configuration */
+       if (clock->alias) {
+               on_index = mod->alias_on_index;
+               on_bit = mod->alias_on_bit;
+       } else {
+               on_index = clock->on_index;
+               on_bit = clock->on_bit;
+       }
+
+       for (i = 0; i < priv->num_pair_clks; i++) {
+               if (priv->pair_clks[i].on_index == on_index &&
+                   priv->pair_clks[i].on_bit == on_bit) {
+                       clock->pair_clk = &priv->pair_clks[i];
+                       pr_err("cpg: 2: register paired clock %s
on_index %u on_bit %u num:%u\n",
+                       clock->hw.init->name, on_index, on_bit,
+                       priv->num_pair_clks);
+                       return 0;
+               }
+       }
+
+       priv->num_pair_clks++;
+       priv->pair_clks = devm_krealloc(priv->dev, priv->pair_clks,
+                                       sizeof(*priv->pair_clks) *
priv->num_pair_clks, GFP_KERNEL);
+       if (!priv->pair_clks)
+               return -ENOMEM;
+
+       pr_err("cpg: register paired clock %s on_index %u on_bit %u num:%u\n",
+              clock->hw.init->name, on_index, on_bit,
+              priv->num_pair_clks);
+       priv->pair_clks[priv->num_pair_clks - 1].on_index = on_index;
+       priv->pair_clks[priv->num_pair_clks - 1].on_bit = on_bit;
+       priv->pair_clks[priv->num_pair_clks - 1].enabled_count = 0;
+       clock->pair_clk = &priv->pair_clks[priv->num_pair_clks - 1];
+
+       return 0;
+}
+
 static void __init
 rzv2h_cpg_register_mod_clk(const struct rzv2h_mod_clk *mod,
                           struct rzv2h_cpg_priv *priv)
@@ -966,7 +1072,13 @@ rzv2h_cpg_register_mod_clk(const struct
rzv2h_mod_clk *mod,
        clock->priv = priv;
        clock->hw.init = &init;
        clock->mstop_data = mod->mstop_data;
-
+       clock->paired = mod->paired;
+       clock->alias = mod->alias;
+       ret = rzv2h_mod_clk_get_paired_cfg(priv, clock, mod);
+       if (ret) {
+               clk = ERR_PTR(ret);
+               goto fail;
+       }
        ret = devm_clk_hw_register(dev, &clock->hw);
        if (ret) {
                clk = ERR_PTR(ret);
diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h
index bce131bec80b..87b62fc908ba 100644
--- a/drivers/clk/renesas/rzv2h-cpg.h
+++ b/drivers/clk/renesas/rzv2h-cpg.h
@@ -223,6 +223,11 @@ enum clk_types {
  * @mon_index: monitor register index
  * @mon_bit: monitor bit
  * @ext_clk_mux_index: mux index for external clock source, or -1 if internal
+ * @paired: indicates if this clock is paired with another clock,
i.e., it shares
+ *          the same ON bit and has a separate MON bit.
+ * @alias: indicates if this clock is paired and has been given dummy ON bit
+ * @alias_on_index: For paired clocks, the index of the alias ON bit
+ * @alias_on_bit: For paired clocks, the index of the alias ON bit
  */
 struct rzv2h_mod_clk {
        const char *name;
@@ -235,10 +240,15 @@ struct rzv2h_mod_clk {
        s8 mon_index;
        u8 mon_bit;
        s8 ext_clk_mux_index;
+       bool paired;
+       bool alias;
+       u8 alias_on_index;
+       u8 alias_on_bit;
 };

 #define DEF_MOD_BASE(_name, _mstop, _parent, _critical, _no_pm, _onindex, \
-                    _onbit, _monindex, _monbit, _ext_clk_mux_index) \
+                    _onbit, _monindex, _monbit, _ext_clk_mux_index, _paired, \
+                    _alias, _alias_on_index, _alias_on_bit) \
        { \
                .name = (_name), \
                .mstop_data = (_mstop), \
@@ -250,23 +260,40 @@ struct rzv2h_mod_clk {
                .mon_index = (_monindex), \
                .mon_bit = (_monbit), \
                .ext_clk_mux_index = (_ext_clk_mux_index), \
+               .paired = (_paired), \
+               .alias = (_alias), \
+               .alias_on_index = (_alias_on_index), \
+               .alias_on_bit = (_alias_on_bit), \
        }

 #define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \
-       DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex,
_onbit, _monindex, _monbit, -1)
+       DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, \
+                    _monindex, _monbit, -1, false, false, 0, 0)

 #define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex,
_monbit, _mstop) \
-       DEF_MOD_BASE(_name, _mstop, _parent, true, false, _onindex,
_onbit, _monindex, _monbit, -1)
+       DEF_MOD_BASE(_name, _mstop, _parent, true, false, _onindex,
_onbit, _monindex, \
+                    _monbit, -1, false, false, 0, 0)

 #define DEF_MOD_NO_PM(_name, _parent, _onindex, _onbit, _monindex,
_monbit, _mstop) \
-       DEF_MOD_BASE(_name, _mstop, _parent, false, true, _onindex,
_onbit, _monindex, _monbit, -1)
+       DEF_MOD_BASE(_name, _mstop, _parent, false, true, _onindex,
_onbit, _monindex, \
+                    _monbit, -1, false, false, 0, 0)

 #define DEF_MOD_MUX_EXTERNAL(_name, _parent, _onindex, _onbit,
_monindex, _monbit, _mstop, \
                             _ext_clk_mux_index) \
        DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex,
_onbit, _monindex, _monbit, \
-                    _ext_clk_mux_index)
+                    _ext_clk_mux_index, false, false, 0, 0)

-/**
+#define DEF_MOD_PAIRED(_name, _parent, _onindex, _onbit, _monindex,
_monbit, _mstop) \
+       DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex,
_onbit, _monindex, \
+                    _monbit, -1, true, false, 0, 0)
+
+#define DEF_MOD_PAIRED_ALIAS(_name, _parent, _onindex, _onbit,
_monindex, _monbit, _mstop, \
+                            _alias_on_index, _alias_on_bit) \
+       DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex,
_onbit, _monindex, _monbit, -1, \
+                    true, true, _alias_on_index, _alias_on_bit)
+
+
+ /**
  * struct rzv2h_reset - Reset definitions
  *
  * @reset_index: reset register index



# Output when module is loaded
root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi
             spi_aclk                0       1        0
200000000   0          0     50000      N               deviceless
                 of_clk_get_from_provider
             spi_hclk                0       1        0
200000000   0          0     50000      N               deviceless
                 of_clk_get_from_provider
          .smux2_xspi_clk0           1       1        0
533333333   0          0     50000      Y            deviceless
              no_connection_id
             .smux2_xspi_clk1        1       1        0
533333333   0          0     50000      Y               deviceless
                 no_connection_id
                .pllcm33_xspi        2       2        0
133333334   0          0     50000      Y                  deviceless
                    no_connection_id
                   spi_clk_spi       1       2        0
133333334   0          0     50000      Y
11030000.spi                    spi
                   .pllcm33_xspix2   1       1        0
266666668   0          0     50000      Y
deviceless                      no_connection_id
                      spi_clk_spix2  1       2        0
266666668   0          0     50000      Y
11030000.spi                    spix2


# Output when module is unloaded
root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi
             spi_aclk                0       0        0
200000000   0          0     50000      N               deviceless
                 no_connection_id
             spi_hclk                0       0        0
200000000   0          0     50000      N               deviceless
                 no_connection_id
          .smux2_xspi_clk0           0       0        0
533333333   0          0     50000      Y            deviceless
              no_connection_id
             .smux2_xspi_clk1        0       0        0
533333333   0          0     50000      Y               deviceless
                 no_connection_id
                .pllcm33_xspi        0       0        0
133333334   0          0     50000      Y                  deviceless
                    no_connection_id
                   spi_clk_spi       0       0        0
133333334   0          0     50000      N
deviceless                      no_connection_id
                   .pllcm33_xspix2   0       0        0
266666668   0          0     50000      Y
deviceless                      no_connection_id
                      spi_clk_spix2  0       0        0
266666668   0          0     50000      N
deviceless                      no_connection_id
root@rzv2h-evk:~#
root@rzv2h-evk:~#


Cheers,
Prabhakar





[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux