Skip to content

Commit 893f109

Browse files
author
deooi
committed
pl35x-nand-controller: Enable dynamic clk rate setting
Bluefin devices require different clk frequencies to be set at different timing modes. Enable the memclk rate to be set according to the specifications in the device tree. If the device tree does not have this memclk-timing-frequency property specified, the driver proceeds as usual. Signed-off-by: deooi <deborah.ooi@ni.com>
1 parent 76c9aec commit 893f109

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

arch/arm/boot/dts/xilinx/ni-zynq.dtsi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,16 @@
140140

141141
&smcc {
142142
status = "okay";
143+
/*
144+
* Bluefin devices require different memclk frequency
145+
* for different timing modes
146+
*/
147+
memclk-timing-frequency = <0 83333333>,
148+
<1 166666666>,
149+
<2 166666666>,
150+
<3 166666666>,
151+
<4 166666666>,
152+
<5 166666666>;
143153
};
144154

145155
&nfc0 {

drivers/mtd/nand/raw/pl35x-nand-controller.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,22 @@ static int pl35x_nfc_exec_op(struct nand_chip *chip,
795795
op, check_only);
796796
}
797797

798+
static unsigned long get_special_timing_freq(const struct device_node *np, int timing_mode)
799+
{
800+
int len, i;
801+
802+
const __be32 *memclk_timing_freq = of_get_property(np, "memclk-timing-frequency", &len);
803+
804+
if (memclk_timing_freq) {
805+
for (i = 0; i < len / sizeof(u32) / 2; i++) {
806+
if (timing_mode == be32_to_cpu(memclk_timing_freq[i * 2])) {
807+
return be32_to_cpu(memclk_timing_freq[i * 2 + 1]);
808+
};
809+
}
810+
}
811+
return 0;
812+
}
813+
798814
static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs,
799815
const struct nand_interface_config *conf)
800816
{
@@ -804,6 +820,8 @@ static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs,
804820
const struct nand_sdr_timings *sdr;
805821
unsigned int period_ns, val;
806822
struct clk *mclk;
823+
unsigned long special_timing_freq;
824+
int ret = 0;
807825

808826
sdr = nand_get_sdr_timings(conf);
809827
if (IS_ERR(sdr))
@@ -815,6 +833,20 @@ static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs,
815833
return PTR_ERR(mclk);
816834
}
817835

836+
/*
837+
* Bluefin devices require different rates for different timing modes
838+
* so we need to set the rate according to the timing modes
839+
*/
840+
special_timing_freq = get_special_timing_freq(
841+
nfc->dev->parent->of_node,
842+
conf->timings.mode);
843+
844+
if (special_timing_freq) {
845+
ret = clk_set_rate(mclk, special_timing_freq);
846+
if (ret)
847+
return -EINVAL;
848+
}
849+
818850
/*
819851
* SDR timings are given in pico-seconds while NFC timings must be
820852
* expressed in NAND controller clock cycles. We use the TO_CYCLE()

0 commit comments

Comments
 (0)