This series contains all the changes necessary to make SATA work on
the da850-lcdk board.
The first patch adds DT bindings for the ahci-da850 driver.
The second enables relevant modules in davinci_all_defconfig.
Patches 03/14-06/14 modify the way the clocks are handled regarding
SATA on the da850 platform. We modify the ahci driver to retrieve
the clock via con_id and model the external SATA oscillator as
a real clock.
Patches 07/14-11/14 extend the ahci-da850 driver. Add DT support,
implement workarounds necessary to make SATA work on the da850-lcdk
board and un-hardcode the external clock multiplier.
Last three patches add device tree changes required to probe the
driver.
v1 -> v2:
- dropped patch 04/10 - replaced with local changes in the
ahci-da850 driver
- added comments explaining the workaround in ahci softreset
- s/0x218000/218000 in the sata DT node label
- added patches chaning the way clocks are handled in the da850 SATA
code both in arch/ and in the ahci driver
- dropped the clock multiplier property in the DT bindings in favor
of using struct clk to pass the refclk rate to the driver
- minor tweaks in commit messages
Bartosz Golaszewski (14):
devicetree: bindings: add bindings for ahci-da850
ARM: davinci_all_defconfig: enable SATA modules
ARM: davinci: add a clock lookup entry for the SATA clock
sata: ahci-da850: get the sata clock using a connector id
ARM: davinci: da850: add con_id for the SATA clock
ARM: davinci: da850: model the SATA refclk
sata: ahci-da850: add device tree match table
sata: ahci-da850: implement a workaround for the softreset quirk
sata: ahci: export ahci_do_hardreset() locally
sata: ahci-da850: add a workaround for controller instability
sata: ahci-da850: un-hardcode the MPY bits
ARM: dts: da850: add pinmux settings for the SATA controller
ARM: dts: da850: add the SATA node
ARM: dts: da850-lcdk: enable the SATA node
.../devicetree/bindings/ata/ahci-da850.txt | 18 +++
arch/arm/boot/dts/da850-lcdk.dts | 4 +
arch/arm/boot/dts/da850.dtsi | 30 ++++
arch/arm/configs/davinci_all_defconfig | 2 +
arch/arm/mach-davinci/da850.c | 2 +-
arch/arm/mach-davinci/da8xx-dt.c | 9 ++
arch/arm/mach-davinci/devices-da8xx.c | 23 +++
arch/arm/mach-davinci/include/mach/da8xx.h | 1 +
drivers/ata/ahci.h | 3 +
drivers/ata/ahci_da850.c | 172 +++++++++++++++++++--
drivers/ata/libahci.c | 18 ++-
11 files changed, 262 insertions(+), 20 deletions(-)
create mode 100644 Documentation/devicetree/bindings/ata/ahci-da850.txt
--
2.9.3
@@ -0,0 +1,18 @@+Device tree binding for the TI DA850 AHCI SATA Controller+---------------------------------------------------------++Required properties:+ - compatible: must be "ti,da850-ahci"+ - reg: physical base addresses and sizes of the controller's register areas+ - interrupts: interrupt specifier (refer to the interrupt binding)++Optional properties:+ - clocks: clock specifier (refer to the common clock binding)++Example:++ sata: ahci at 218000 {+ compatible = "ti,da850-ahci";+ reg = <0x218000 0x2000>, <0x22c018 0x4>;+ interrupts = <67>;+ };
This entry is needed for the ahci driver to get a functional clock.
Signed-off-by: Bartosz Golaszewski <redacted>
---
arch/arm/mach-davinci/da8xx-dt.c | 1 +
1 file changed, 1 insertion(+)
The ahci-da850 SATA driver is now capable of retrieving clocks by
con_id. Add the connector id for the sysclk2-derived SATA clock.
Signed-off-by: Bartosz Golaszewski <redacted>
---
arch/arm/mach-davinci/da850.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
We have a use case with the da850 SATA controller where at PLL0
frequency of 456MHz (needed to properly service the LCD controller)
the chip becomes unstable and the hardreset operation is ignored the
first time 50% of times.
The sata core driver already retries to resume the link because some
controllers ignore writes to the SControl register, but just retrying
the resume operation doesn't work - we need to issue he phy/wake reset
again to make it work.
Reimplement ahci_hardreset() in the driver and poke the controller a
couple times before really giving up.
Signed-off-by: Bartosz Golaszewski <redacted>
---
drivers/ata/ahci_da850.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
In order to make the MPY bits configurable, try to obtain the refclk
and calculate the required multiplier from its rate.
If we fail to get the clock, fall back to the default value which
keeps backwards compatibility.
Signed-off-by: Bartosz Golaszewski <redacted>
---
drivers/ata/ahci_da850.c | 88 +++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 76 insertions(+), 12 deletions(-)
@@ -126,9 +168,10 @@ static int ahci_da850_probe(struct platform_device *pdev){structdevice*dev=&pdev->dev;structahci_host_priv*hpriv;-structresource*res;void__iomem*pwrdn_reg;+structresource*res;structclk*clk;+u32mpy;intrc;hpriv=ahci_platform_get_resources(pdev);
@@ -150,6 +193,27 @@ static int ahci_da850_probe(struct platform_device *pdev)hpriv->clks[0]=clk;}+/*+*Thesecondclockusedbyahci-da850istheexternalREFCLK.Ifwe+*didn'tgetitfromahci_platform_get_resources(),let'stryto+*specifythecon_idinclk_get().Ifwestilldon'tgetaclock,+*we'llusethedefaultvaluethatworksfortheda850-evmboard.+*/+if(!hpriv->clks[1]){+clk=clk_get(dev,"refclk");+if(IS_ERR(clk))+hpriv->clks[1]=NULL;+else+hpriv->clks[1]=clk;+}++if(!hpriv->clks[1]){+dev_info(dev,"unable to obtain the reference clock - using default multiplier");+mpy=DA850_SATA_MPY_DEFAULT;+}else{+mpy=ahci_da850_calculate_mpy(clk_get_rate(hpriv->clks[1]));+}+rc=ahci_platform_enable_resources(hpriv);if(rc)returnrc;
@@ -162,7 +226,7 @@ static int ahci_da850_probe(struct platform_device *pdev)if(!pwrdn_reg)gotodisable_resources;-da850_sata_init(dev,pwrdn_reg,hpriv->mmio);+da850_sata_init(dev,pwrdn_reg,hpriv->mmio,mpy);rc=ahci_platform_init_host(pdev,hpriv,&ahci_da850_port_info,&ahci_platform_sht);
Enable the SATA node for da850-lcdk. We omit the pinctrl property on
purpose - the muxed SATA pins are not hooked up to anything
SATA-related on the lcdk.
The REFCLKN/P rate on the board is 100MHz, so we need a multiplier of
15 for 1.5GHz PLL rate.
Signed-off-by: Bartosz Golaszewski <redacted>
---
arch/arm/boot/dts/da850-lcdk.dts | 4 ++++
1 file changed, 4 insertions(+)
We need a way to retrieve the information about the online state of
the link in the ahci-da850 driver.
Create a new function: ahci_do_hardreset() which is called from
ahci_hardreset() for backwards compatibility, but has an additional
argument: 'online' - which can be used to check if the link is online
after this function returns.
The new routine will be used in the ahci-da850 driver to avoid code
duplication when implementing a workaround for tha da850 SATA
controller quirk/instability.
Signed-off-by: Bartosz Golaszewski <redacted>
---
drivers/ata/ahci.h | 3 +++
drivers/ata/libahci.c | 18 +++++++++++++-----
2 files changed, 16 insertions(+), 5 deletions(-)
We're using device tree for da850-lcdk. Add the match table to allow
to probe the driver.
Signed-off-by: Bartosz Golaszewski <redacted>
---
drivers/ata/ahci_da850.c | 7 +++++++
1 file changed, 7 insertions(+)
There's an issue with the da850 SATA controller: if port multiplier
support is compiled in, but we're connecting the drive directly to
the SATA port on the board, the drive can't be detected.
To make SATA work on the da850-lcdk board: first try to softreset
with pmp - if the operation fails with -EBUSY, retry without pmp.
Signed-off-by: Bartosz Golaszewski <redacted>
---
drivers/ata/ahci_da850.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
In preparation for using two clocks in the driver (the sysclk2-based
clock and the external REFCLK), check if we got a functional clock
after calling ahci_platform_get_resources(). If not, retry calling
get_clk() with con_id specified.
Signed-off-by: Bartosz Golaszewski <redacted>
---
drivers/ata/ahci_da850.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
Register a dummy clock modelling the external SATA oscillator for
da850 DT mode. For non-DT boot we don't register the clock - instead
we rely on the default MPY value defined in the da850 ahci driver (as
is done currently).
Signed-off-by: Bartosz Golaszewski <redacted>
---
arch/arm/mach-davinci/da8xx-dt.c | 8 ++++++++
arch/arm/mach-davinci/devices-da8xx.c | 23 +++++++++++++++++++++++
arch/arm/mach-davinci/include/mach/da8xx.h | 1 +
3 files changed, 32 insertions(+)
From: Sergei Shtylyov <hidden> Date: 2017-01-17 16:03:01
Hello!
On 01/17/2017 03:26 PM, Bartosz Golaszewski wrote:
In preparation for using two clocks in the driver (the sysclk2-based
clock and the external REFCLK), check if we got a functional clock
after calling ahci_platform_get_resources(). If not, retry calling
get_clk() with con_id specified.
@@ -0,0 +1,18 @@+Device tree binding for the TI DA850 AHCI SATA Controller+---------------------------------------------------------++Required properties:+ - compatible: must be "ti,da850-ahci"+ - reg: physical base addresses and sizes of the controller's register areas+ - interrupts: interrupt specifier (refer to the interrupt binding)++Optional properties:+ - clocks: clock specifier (refer to the common clock binding)
Won't you also need a clock-names property since there are two clocks?
From: David Lechner <david@lechnology.com> Date: 2017-01-17 18:51:51
On 01/17/2017 06:26 AM, Bartosz Golaszewski wrote:
In order to make the MPY bits configurable, try to obtain the refclk
and calculate the required multiplier from its rate.
If we fail to get the clock, fall back to the default value which
keeps backwards compatibility.
It seems like it would be wiser to make is so that if we fail to get the
clock, it is an error. This way, if someone makes a new board and
forgets to configure a clock, they will get an error instead of
wondering why things are not working because it is using the wrong
multiplier.
From: David Lechner <david@lechnology.com> Date: 2017-01-17 18:54:02
On 01/17/2017 06:26 AM, Bartosz Golaszewski wrote:
Enable the SATA node for da850-lcdk. We omit the pinctrl property on
purpose - the muxed SATA pins are not hooked up to anything
SATA-related on the lcdk.
The REFCLKN/P rate on the board is 100MHz, so we need a multiplier of
15 for 1.5GHz PLL rate.
The multiplier is no longer in device tree, so this comment is not
necessary.
From: David Lechner <david@lechnology.com> Date: 2017-01-17 20:34:08
On 01/17/2017 06:26 AM, Bartosz Golaszewski wrote:
Register a dummy clock modelling the external SATA oscillator for
da850 DT mode. For non-DT boot we don't register the clock - instead
we rely on the default MPY value defined in the da850 ahci driver (as
is done currently).
@@ -0,0 +1,18 @@+Device tree binding for the TI DA850 AHCI SATA Controller+---------------------------------------------------------++Required properties:+ - compatible: must be "ti,da850-ahci"+ - reg: physical base addresses and sizes of the controller's
register areas
+ - interrupts: interrupt specifier (refer to the interrupt binding)
+
+Optional properties:
+ - clocks: clock specifier (refer to the common clock binding)
Won't you also need a clock-names property since there are two clocks?
It would be nice to have clocks and clock-names in the example as well.
Well, we don't use the common clock binding today. Is it really
necessary to add them now. Thats basically going to remain completely
untested.
I would drop the mention of clocks specification as an optional property
too.
Thanks,
Sekhar
From: Sekhar Nori <hidden> Date: 2017-01-18 09:29:35
On Tuesday 17 January 2017 05:56 PM, Bartosz Golaszewski wrote:
Register a dummy clock modelling the external SATA oscillator for
I would not call it a dummy clock. Its representing something physically
present. Just call it "fixed rate clock" ?
da850 DT mode. For non-DT boot we don't register the clock - instead
we rely on the default MPY value defined in the da850 ahci driver (as
is done currently).
Here too, like David suggested, it will be nice to register it both for
DT and non-DT case. With that I think your driver will be simple too
since you dont have to worry about the case when refclkpn is not supplied.
Since all supported boards use 100 Mhz refclk anyway, I would drop the
machine check and just do:
/* All existing boards use 100MHz SATA refclkpn */
unsigned long sata_refclkpn = 100 * 1000 * 1000;
ret = da850_register_sata_refclk(sata_refclkpn);
It should then be easy for the odd board (when it comes) to set
sata_refclkpn to a different value.
Thanks,
Sekhar